Backed out 6 changesets (bug 939318) for Windows xpcshell failures on a CLOSED TREE.

Backed out changeset faece15110ef (bug 939318)
Backed out changeset ecc0368d9283 (bug 939318)
Backed out changeset 4dcb889cf913 (bug 939318)
Backed out changeset 2fe8c65c26c2 (bug 939318)
Backed out changeset 0b9c1bbc7826 (bug 939318)
Backed out changeset fc191ae0a0e8 (bug 939318)
This commit is contained in:
Ryan VanderMeulen 2014-08-29 14:22:47 -04:00
parent 8ae7ff2a44
commit 84bb6ce5ad
29 changed files with 147 additions and 759 deletions

View File

@ -990,10 +990,6 @@ pref("security.fileuri.strict_origin_policy", true);
// the results
pref("network.allow-experiments", true);
// Allow the network changed event to get sent when a network topology or
// setup change is noticed while running.
pref("network.notify.changed", true);
// Transmit UDP busy-work to the LAN when anticipating low latency
// network reads and on wifi to mitigate 802.11 Power Save Polling delays
pref("network.tickle-wifi.enabled", false);
@ -1170,11 +1166,6 @@ pref("network.http.connection-retry-timeout", 250);
// to give up if the OS does not give up first
pref("network.http.connection-timeout", 90);
// The number of seconds to allow active connections to prove that they have
// traffic before considered stalled, after a network change has been detected
// and signalled.
pref("network.http.network-changed.timeout", 5);
// The maximum number of current global half open sockets allowable
// when starting a new speculative connection.
pref("network.http.speculative-parallel-limit", 6);

View File

@ -10,7 +10,7 @@
/**
* Network link status monitoring service.
*/
[scriptable, uuid(2deead82-1d29-45f5-8c59-5dbee477cff8)]
[scriptable, uuid(f7d3be87-7403-4a1e-b89f-2797776e9b08)]
interface nsINetworkLinkService : nsISupports
{
/* Link type constants */
@ -64,11 +64,6 @@ interface nsINetworkLinkService : nsISupports
* isLinkUp is now false, linkStatusKnown is true.
*/
#define NS_NETWORK_LINK_DATA_DOWN "down"
/**
* isLinkUp is still true, but the network setup is modified.
* linkStatusKnown is true.
*/
#define NS_NETWORK_LINK_DATA_CHANGED "changed"
/**
* linkStatusKnown is now false.
*/

View File

@ -37,7 +37,6 @@
#include "nsPIDNSService.h"
#include "nsIProtocolProxyService2.h"
#include "MainThreadUtils.h"
#include "nsIWidget.h"
#if defined(XP_WIN)
#include "nsNativeConnectionHelper.h"
@ -55,15 +54,14 @@ using namespace mozilla;
// but the old names are still used to preserve backward compatibility.
#define NECKO_BUFFER_CACHE_COUNT_PREF "network.buffer.cache.count"
#define NECKO_BUFFER_CACHE_SIZE_PREF "network.buffer.cache.size"
#define NETWORK_NOTIFY_CHANGED_PREF "network.notify.changed"
#define MAX_RECURSION_COUNT 50
nsIOService* gIOService = nullptr;
static bool gHasWarnedUploadChannel2;
// A general port blacklist. Connections to these ports will not be allowed
// unless the protocol overrides.
// A general port blacklist. Connections to these ports will not be allowed unless
// the protocol overrides.
//
// TODO: I am sure that there are more ports to be added.
// This cut is based on the classic mozilla codebase
@ -150,7 +148,6 @@ nsIOService::nsIOService()
, mNetworkLinkServiceInitialized(false)
, mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
, mAutoDialEnabled(false)
, mNetworkNotifyChanged(true)
{
}
@ -190,7 +187,6 @@ nsIOService::Init()
prefBranch->AddObserver(MANAGE_OFFLINE_STATUS_PREF, this, true);
prefBranch->AddObserver(NECKO_BUFFER_CACHE_COUNT_PREF, this, true);
prefBranch->AddObserver(NECKO_BUFFER_CACHE_SIZE_PREF, this, true);
prefBranch->AddObserver(NETWORK_NOTIFY_CHANGED_PREF, this, true);
PrefsChanged(prefBranch);
}
@ -203,7 +199,6 @@ nsIOService::Init()
observerService->AddObserver(this, kProfileDoChange, true);
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true);
observerService->AddObserver(this, NS_WIDGET_WAKE_OBSERVER_TOPIC, true);
}
else
NS_WARNING("failed to get observer service");
@ -270,9 +265,10 @@ nsIOService::InitializeNetworkLinkService()
// so let's cross our fingers!
mManageOfflineStatus = false;
}
if (mManageOfflineStatus)
OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN);
TrackNetworkLinkStatusForOffline();
else
SetOffline(false);
@ -855,14 +851,6 @@ nsIOService::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
gDefaultSegmentSize = size;
NS_WARN_IF_FALSE( (!(size & (size - 1))) , "network segment size is not a power of 2!");
}
if (!pref || strcmp(pref, NETWORK_NOTIFY_CHANGED_PREF) == 0) {
bool allow;
nsresult rv = prefs->GetBoolPref(NETWORK_NOTIFY_CHANGED_PREF, &allow);
if (NS_SUCCEEDED(rv)) {
mNetworkNotifyChanged = allow;
}
}
}
void
@ -923,20 +911,23 @@ nsIOService::Observe(nsISupports *subject,
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
if (prefBranch)
PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
} else if (!strcmp(topic, kProfileChangeNetTeardownTopic)) {
}
else if (!strcmp(topic, kProfileChangeNetTeardownTopic)) {
if (!mOffline) {
mOfflineForProfileChange = true;
SetOffline(true);
}
} else if (!strcmp(topic, kProfileChangeNetRestoreTopic)) {
}
else if (!strcmp(topic, kProfileChangeNetRestoreTopic)) {
if (mOfflineForProfileChange) {
mOfflineForProfileChange = false;
if (!mManageOfflineStatus ||
NS_FAILED(OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN))) {
NS_FAILED(TrackNetworkLinkStatusForOffline())) {
SetOffline(false);
}
}
} else if (!strcmp(topic, kProfileDoChange)) {
}
else if (!strcmp(topic, kProfileDoChange)) {
if (data && NS_LITERAL_STRING("startup").Equals(data)) {
// Lazy initialization of network link service (see bug 620472)
InitializeNetworkLinkService();
@ -948,7 +939,8 @@ nsIOService::Observe(nsISupports *subject,
GetPrefBranch(getter_AddRefs(prefBranch));
PrefsChanged(prefBranch, MANAGE_OFFLINE_STATUS_PREF);
}
} else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
}
else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
// Remember we passed XPCOM shutdown notification to prevent any
// changes of the offline status from now. We must not allow going
// online after this point.
@ -958,25 +950,13 @@ nsIOService::Observe(nsISupports *subject,
// Break circular reference.
mProxyService = nullptr;
} else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
if (!mOfflineForProfileChange) {
OnNetworkLinkEvent(NS_ConvertUTF16toUTF8(data).get());
}
} else if (!strcmp(topic, NS_WIDGET_WAKE_OBSERVER_TOPIC)) {
// coming back alive from sleep
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
NS_ASSERTION(observerService, "The observer service should not be null");
if (observerService && mNetworkNotifyChanged) {
(void)observerService->
NotifyObservers(nullptr,
NS_NETWORK_LINK_TOPIC,
MOZ_UTF16(NS_NETWORK_LINK_DATA_CHANGED));
}
else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
if (!mOfflineForProfileChange && mManageOfflineStatus) {
TrackNetworkLinkStatusForOffline();
}
}
return NS_OK;
}
@ -1074,25 +1054,24 @@ nsIOService::NewSimpleNestedURI(nsIURI* aURI, nsIURI** aResult)
}
NS_IMETHODIMP
nsIOService::SetManageOfflineStatus(bool aManage)
{
nsIOService::SetManageOfflineStatus(bool aManage) {
nsresult rv = NS_OK;
// SetManageOfflineStatus must throw when we fail to go from non-managed
// to managed. Usually because there is no link monitoring service
// available. Failure to do this switch is detected by a failure of
// OnNetworkLinkEvent(). When there is no network link available during
// call to InitializeNetworkLinkService(), application is put to offline
// mode. And when we change mMangeOfflineStatus to false on the next line
// we get stuck on being offline even though the link becomes later
// available.
// to managed. Usually because there is no link monitoring service
// available. Failure to do this switch is detected by a failure of
// TrackNetworkLinkStatusForOffline(). When there is no network link
// available during call to InitializeNetworkLinkService(), application is
// put to offline mode. And when we change mMangeOfflineStatus to false
// on the next line we get stuck on being offline even though the link
// becomes later available.
bool wasManaged = mManageOfflineStatus;
mManageOfflineStatus = aManage;
InitializeNetworkLinkService();
if (mManageOfflineStatus && !wasManaged) {
rv = OnNetworkLinkEvent(NS_NETWORK_LINK_DATA_UNKNOWN);
rv = TrackNetworkLinkStatusForOffline();
if (NS_FAILED(rv))
mManageOfflineStatus = false;
}
@ -1105,57 +1084,41 @@ nsIOService::GetManageOfflineStatus(bool* aManage) {
return NS_OK;
}
// input argument 'data' is already UTF8'ed
nsresult
nsIOService::OnNetworkLinkEvent(const char *data)
nsIOService::TrackNetworkLinkStatusForOffline()
{
NS_ASSERTION(mManageOfflineStatus,
"Don't call this unless we're managing the offline status");
if (!mNetworkLinkService)
return NS_ERROR_FAILURE;
if (mShutdown)
return NS_ERROR_NOT_AVAILABLE;
if (mManageOfflineStatus)
return NS_OK;
if (!strcmp(data, NS_NETWORK_LINK_DATA_DOWN)) {
// check to make sure this won't collide with Autodial
if (mSocketTransportService) {
bool autodialEnabled = false;
mSocketTransportService->GetAutodialEnabled(&autodialEnabled);
// If autodialing-on-link-down is enabled, check if the OS auto
// dial option is set to always autodial. If so, then we are
// always up for the purposes of offline management.
if (autodialEnabled) {
// check to make sure this won't collide with Autodial
if (mSocketTransportService) {
bool autodialEnabled = false;
mSocketTransportService->GetAutodialEnabled(&autodialEnabled);
// If autodialing-on-link-down is enabled, check if the OS auto dial
// option is set to always autodial. If so, then we are
// always up for the purposes of offline management.
if (autodialEnabled) {
#if defined(XP_WIN)
// On Windows, we should first check with the OS to see if
// autodial is enabled. If it is enabled then we are allowed
// to manage the offline state.
if (nsNativeConnectionHelper::IsAutodialEnabled()) {
return SetOffline(false);
}
#else
// On Windows, we should first check with the OS
// to see if autodial is enabled. If it is
// enabled then we are allowed to manage the
// offline state.
if(nsNativeConnectionHelper::IsAutodialEnabled())
return SetOffline(false);
#else
return SetOffline(false);
#endif
}
}
}
bool isUp;
if (!strcmp(data, NS_NETWORK_LINK_DATA_DOWN)) {
isUp = false;
} else if (!strcmp(data, NS_NETWORK_LINK_DATA_UP)) {
isUp = true;
} else if (!strcmp(data, NS_NETWORK_LINK_DATA_CHANGED)) {
// CHANGED events are handled by others
return NS_OK;
} else if (!strcmp(data, NS_NETWORK_LINK_DATA_UNKNOWN)) {
nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp);
NS_ENSURE_SUCCESS(rv, rv);
} else {
NS_WARNING("Unhandled network event!");
return NS_OK;
}
nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp);
NS_ENSURE_SUCCESS(rv, rv);
return SetOffline(!isUp);
}

View File

@ -81,7 +81,7 @@ private:
nsIOService();
~nsIOService();
nsresult OnNetworkLinkEvent(const char *data);
nsresult TrackNetworkLinkStatusForOffline();
nsresult GetCachedProtocolHandler(const char *scheme,
nsIProtocolHandler* *hdlrResult,
@ -129,7 +129,6 @@ private:
nsTArray<int32_t> mRestrictedPortList;
bool mAutoDialEnabled;
bool mNetworkNotifyChanged;
public:
// Used for all default buffer sizes that necko allocates.
static uint32_t gDefaultSegmentSize;

View File

@ -29,7 +29,6 @@
#include "mozilla/Mutex.h"
#include "mozilla/CondVar.h"
#include "nsISystemProxySettings.h"
#include "nsINetworkLinkService.h"
//----------------------------------------------------------------------------
@ -415,15 +414,11 @@ nsProtocolProxyService::Init()
PrefsChanged(prefBranch, nullptr);
}
// register for shutdown notification so we can clean ourselves up properly.
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
// register for shutdown notification so we can clean ourselves up
// properly.
if (obs)
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
obs->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
}
return NS_OK;
}
@ -445,13 +440,6 @@ nsProtocolProxyService::Observe(nsISupports *aSubject,
mPACMan->Shutdown();
mPACMan = nullptr;
}
} else if (strcmp(aTopic, NS_NETWORK_LINK_TOPIC) == 0) {
nsCString converted = NS_ConvertUTF16toUTF8(aData);
const char *state = converted.get();
if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED) == 0) {
LOG((": received network event: %s, reload PAC", state));
ReloadPAC();
}
}
else {
NS_ASSERTION(strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,

View File

@ -30,15 +30,12 @@
#include "nsCharSeparatedTokenizer.h"
#include "nsNetAddr.h"
#include "nsProxyRelease.h"
#include "nsIObserverService.h"
#include "nsINetworkLinkService.h"
#include "mozilla/Attributes.h"
#include "mozilla/VisualEventTracer.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/net/ChildDNSService.h"
#include "mozilla/net/DNSListenerProxy.h"
#include "mozilla/Services.h"
using namespace mozilla;
using namespace mozilla::net;
@ -543,13 +540,12 @@ nsDNSService::Init()
prefs->AddObserver("network.proxy.type", this, false);
}
nsresult rv;
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
do_GetService("@mozilla.org/observer-service;1", &rv);
if (NS_SUCCEEDED(rv)) {
observerService->AddObserver(this, "last-pb-context-exited", false);
observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
}
}
nsDNSPrefetch::Initialize(this);
@ -874,21 +870,10 @@ nsDNSService::GetMyHostName(nsACString &result)
NS_IMETHODIMP
nsDNSService::Observe(nsISupports *subject, const char *topic, const char16_t *data)
{
// We are only getting called if a preference has changed or there's a
// network link event.
// we are only getting called if a preference has changed.
NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0 ||
strcmp(topic, "last-pb-context-exited") == 0 ||
strcmp(topic, NS_NETWORK_LINK_TOPIC) == 0,
"unexpected observe call");
if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
nsCString converted = NS_ConvertUTF16toUTF8(data);
const char *state = converted.get();
if (!strcmp(state, NS_NETWORK_LINK_DATA_CHANGED)) {
mResolver->FlushCache();
}
return NS_OK;
}
strcmp(topic, "last-pb-context-exited") == 0,
"unexpected observe call");
//
// Shutdown and this function are both only called on the UI thread, so we don't

View File

@ -478,8 +478,10 @@ nsHostResolver::ClearPendingQueue(PRCList *aPendingQ)
}
void
nsHostResolver::FlushCache()
nsHostResolver::Shutdown()
{
LOG(("Shutting down host resolver.\n"));
PRCList pendingQHigh, pendingQMed, pendingQLow, evictionQ;
PR_INIT_CLIST(&pendingQHigh);
PR_INIT_CLIST(&pendingQMed);
@ -488,20 +490,23 @@ nsHostResolver::FlushCache()
{
MutexAutoLock lock(mLock);
mShutdown = true;
MoveCList(mHighQ, pendingQHigh);
MoveCList(mMediumQ, pendingQMed);
MoveCList(mLowQ, pendingQLow);
MoveCList(mEvictionQ, evictionQ);
mEvictionQSize = 0;
mPendingCount = 0;
if (mNumIdleThreads)
mIdleThreadCV.NotifyAll();
// empty host database
PL_DHashTableEnumerate(&mDB, HostDB_RemoveEntry, nullptr);
}
ClearPendingQueue(&pendingQHigh);
ClearPendingQueue(&pendingQMed);
ClearPendingQueue(&pendingQLow);
@ -514,18 +519,6 @@ nsHostResolver::FlushCache()
NS_RELEASE(rec);
}
}
}
void
nsHostResolver::Shutdown()
{
LOG(("Shutting down host resolver.\n"));
{
MutexAutoLock lock(mLock);
mShutdown = true;
}
FlushCache();
#ifdef NS_BUILD_REFCNT_LOGGING

View File

@ -238,11 +238,6 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
/**
* Flush the DNS cache.
*/
void FlushCache();
private:
explicit nsHostResolver(uint32_t maxCacheEntries = 50, uint32_t maxCacheLifetime = 60,
uint32_t lifetimeGracePeriod = 0);

View File

@ -39,8 +39,6 @@ public:
return true;
}
virtual void SendPing() = 0;
const static uint32_t kSendingChunkSize = 4095;
const static uint32_t kTCPSendBufferSize = 131072;

View File

@ -98,7 +98,6 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport)
, mOutputQueueSent(0)
, mLastReadEpoch(PR_IntervalNow())
, mPingSentEpoch(0)
, mPreviousUsed(false)
, mWaitingForSettingsAck(false)
, mGoAwayOnPush(false)
{
@ -294,14 +293,8 @@ Http2Session::ReadTimeoutTick(PRIntervalTime now)
if ((now - mLastReadEpoch) < mPingThreshold) {
// recent activity means ping is not an issue
if (mPingSentEpoch) {
if (mPingSentEpoch)
mPingSentEpoch = 0;
if (mPreviousUsed) {
// restore the former value
mPingThreshold = mPreviousPingThreshold;
mPreviousUsed = false;
}
}
return PR_IntervalToSeconds(mPingThreshold) -
PR_IntervalToSeconds(now - mLastReadEpoch);
@ -321,9 +314,8 @@ Http2Session::ReadTimeoutTick(PRIntervalTime now)
LOG3(("Http2Session::ReadTimeoutTick %p generating ping\n", this));
mPingSentEpoch = PR_IntervalNow();
if (!mPingSentEpoch) {
if (!mPingSentEpoch)
mPingSentEpoch = 1; // avoid the 0 sentinel value
}
GeneratePing(false);
ResumeRecv(); // read the ping reply
@ -3301,29 +3293,5 @@ Http2Session::PushBack(const char *buf, uint32_t len)
return mConnection->PushBack(buf, len);
}
void
Http2Session::SendPing()
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
if (mPreviousUsed) {
// alredy in progress, get out
return;
}
mPingSentEpoch = PR_IntervalNow();
if (!mPingSentEpoch) {
mPingSentEpoch = 1; // avoid the 0 sentinel value
}
if (!mPingThreshold ||
(mPingThreshold > gHttpHandler->NetworkChangedTimeout())) {
mPreviousPingThreshold = mPingThreshold;
mPreviousUsed = true;
mPingThreshold = gHttpHandler->NetworkChangedTimeout();
}
GeneratePing(false);
ResumeRecv();
}
} // namespace mozilla::net
} // namespace mozilla

View File

@ -212,8 +212,6 @@ public:
int64_t ServerSessionWindow() { return mServerSessionWindow; }
void DecrementServerSessionWindow (uint32_t bytes) { mServerSessionWindow -= bytes; }
void SendPing() MOZ_OVERRIDE;
private:
// These internal states do not correspond to the states of the HTTP/2 specification
@ -443,9 +441,6 @@ private:
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
PRIntervalTime mPingSentEpoch;
PRIntervalTime mPreviousPingThreshold; // backup for the former value
bool mPreviousUsed; // true when backup is used
// used as a temporary buffer while enumerating the stream hash during GoAway
nsDeque mGoAwayStreamsToRestart;

View File

@ -73,7 +73,6 @@ SpdySession3::SpdySession3(nsISocketTransport *aSocketTransport)
, mLastReadEpoch(PR_IntervalNow())
, mPingSentEpoch(0)
, mNextPingID(1)
, mPreviousUsed(false)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
@ -225,14 +224,8 @@ SpdySession3::ReadTimeoutTick(PRIntervalTime now)
if ((now - mLastReadEpoch) < mPingThreshold) {
// recent activity means ping is not an issue
if (mPingSentEpoch) {
if (mPingSentEpoch)
mPingSentEpoch = 0;
if (mPreviousUsed) {
// restore the former value
mPingThreshold = mPreviousPingThreshold;
mPreviousUsed = false;
}
}
return PR_IntervalToSeconds(mPingThreshold) -
PR_IntervalToSeconds(now - mLastReadEpoch);
@ -2820,34 +2813,5 @@ SpdySession3::PushBack(const char *buf, uint32_t len)
return mConnection->PushBack(buf, len);
}
void
SpdySession3::SendPing()
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
if (mPreviousUsed) {
// alredy in progress, get out
return;
}
mPingSentEpoch = PR_IntervalNow();
if (!mPingSentEpoch) {
mPingSentEpoch = 1; // avoid the 0 sentinel value
}
if (!mPingThreshold ||
(mPingThreshold > gHttpHandler->NetworkChangedTimeout())) {
mPreviousPingThreshold = mPingThreshold;
mPreviousUsed = true;
mPingThreshold = gHttpHandler->NetworkChangedTimeout();
}
GeneratePing(mNextPingID);
mNextPingID += 2;
ResumeRecv();
gHttpHandler->ConnMgr()->ActivateTimeoutTick();
}
} // namespace mozilla::net
} // namespace mozilla

View File

@ -189,8 +189,6 @@ public:
z_stream *UpstreamZlib() { return &mUpstreamZlib; }
nsISocketTransport *SocketTransport() { return mSocketTransport; }
void SendPing() MOZ_OVERRIDE;
private:
enum stateType {
@ -380,9 +378,6 @@ private:
PRIntervalTime mPingSentEpoch;
uint32_t mNextPingID;
PRIntervalTime mPreviousPingThreshold; // backup for the former value
bool mPreviousUsed; // true when backup is used
// used as a temporary buffer while enumerating the stream hash during GoAway
nsDeque mGoAwayStreamsToRestart;

View File

@ -75,7 +75,6 @@ SpdySession31::SpdySession31(nsISocketTransport *aSocketTransport)
, mLastReadEpoch(PR_IntervalNow())
, mPingSentEpoch(0)
, mNextPingID(1)
, mPreviousUsed(false)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
@ -228,14 +227,8 @@ SpdySession31::ReadTimeoutTick(PRIntervalTime now)
if ((now - mLastReadEpoch) < mPingThreshold) {
// recent activity means ping is not an issue
if (mPingSentEpoch) {
if (mPingSentEpoch)
mPingSentEpoch = 0;
if (mPreviousUsed) {
// restore the former value
mPingThreshold = mPreviousPingThreshold;
mPreviousUsed = false;
}
}
return PR_IntervalToSeconds(mPingThreshold) -
PR_IntervalToSeconds(now - mLastReadEpoch);
@ -2964,33 +2957,5 @@ SpdySession31::PushBack(const char *buf, uint32_t len)
return mConnection->PushBack(buf, len);
}
void
SpdySession31::SendPing()
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
if (mPreviousUsed) {
// alredy in progress, get out
return;
}
mPingSentEpoch = PR_IntervalNow();
if (!mPingSentEpoch) {
mPingSentEpoch = 1; // avoid the 0 sentinel value
}
if (!mPingThreshold ||
(mPingThreshold > gHttpHandler->NetworkChangedTimeout())) {
mPreviousPingThreshold = mPingThreshold;
mPreviousUsed = true;
mPingThreshold = gHttpHandler->NetworkChangedTimeout();
}
GeneratePing(mNextPingID);
mNextPingID += 2;
ResumeRecv();
gHttpHandler->ConnMgr()->ActivateTimeoutTick();
}
} // namespace mozilla::net
} // namespace mozilla

View File

@ -193,8 +193,6 @@ public:
int64_t RemoteSessionWindow() { return mRemoteSessionWindow; }
void DecrementRemoteSessionWindow (uint32_t bytes) { mRemoteSessionWindow -= bytes; }
void SendPing() MOZ_OVERRIDE;
private:
enum stateType {
@ -399,9 +397,6 @@ private:
PRIntervalTime mPingSentEpoch;
uint32_t mNextPingID;
PRIntervalTime mPreviousPingThreshold; // backup for the former value
bool mPreviousUsed; // true when backup is used
// used as a temporary buffer while enumerating the stream hash during GoAway
nsDeque mGoAwayStreamsToRestart;

View File

@ -69,7 +69,6 @@ nsHttpConnection::nsHttpConnection()
, mExperienced(false)
, mInSpdyTunnel(false)
, mForcePlainText(false)
, mTrafficStamp(false)
, mHttp1xTransactionCount(0)
, mRemainingConnectionUses(0xffffffff)
, mClassification(nsAHttpTransaction::CLASS_GENERAL)
@ -2081,23 +2080,5 @@ nsHttpConnection::GetInterface(const nsIID &iid, void **result)
return NS_ERROR_NO_INTERFACE;
}
void
nsHttpConnection::CheckForTraffic(bool check)
{
if (check) {
if (mSpdySession) {
// Send a ping to verify it is still alive
mSpdySession->SendPing();
} else {
// If not SPDY, Store snapshot amount of data right now
mTrafficCount = mTotalBytesWritten + mTotalBytesRead;
mTrafficStamp = true;
}
} else {
// mark it as not checked
mTrafficStamp = false;
}
}
} // namespace mozilla::net
} // namespace mozilla

View File

@ -200,20 +200,6 @@ public:
void SetupSecondaryTLS();
void SetInSpdyTunnel(bool arg);
// Returns true if the socket peer has a private (RFC1918-like) address.
bool PeerHasPrivateIP();
// Check active connections for traffic (or not). SPDY connections send a
// ping, ordinary HTTP connections get some time to get traffic to be
// considered alive.
void CheckForTraffic(bool check);
// NoTraffic() returns true if there's been no traffic on the (non-spdy)
// connection since CheckForTraffic() was called.
bool NoTraffic() {
return mTrafficStamp &&
(mTrafficCount == (mTotalBytesWritten + mTotalBytesRead));
}
private:
// Value (set in mTCPKeepaliveConfig) indicates which set of prefs to use.
enum TCPKeepaliveConfig {
@ -306,10 +292,6 @@ private:
bool mInSpdyTunnel;
bool mForcePlainText;
// A snapshot of current number of transfered bytes
int64_t mTrafficCount;
bool mTrafficStamp; // true then the above is set
// The number of <= HTTP/1.1 transactions performed on this connection. This
// excludes spdy transactions.
uint32_t mHttp1xTransactionCount;

View File

@ -85,7 +85,6 @@ nsHttpConnectionMgr::nsHttpConnectionMgr()
, mNumSpdyActiveConns(0)
, mNumHalfOpenConns(0)
, mTimeOfNextWakeUp(UINT64_MAX)
, mPruningNoTraffic(false)
, mTimeoutTickArmed(false)
, mTimeoutTickNext(1)
{
@ -272,8 +271,6 @@ nsHttpConnectionMgr::Observe(nsISupports *subject,
}
else if (timer == mTimeoutTick) {
TimeoutTick();
} else if (timer == mTrafficTimer) {
PruneNoTraffic();
}
else {
MOZ_ASSERT(false, "unexpected timer-callback");
@ -331,25 +328,6 @@ nsHttpConnectionMgr::PruneDeadConnections()
return PostEvent(&nsHttpConnectionMgr::OnMsgPruneDeadConnections);
}
//
// Called after a timeout. Check for active connections that have had no
// traffic since they were "marked" and nuke them.
nsresult
nsHttpConnectionMgr::PruneNoTraffic()
{
LOG(("nsHttpConnectionMgr::PruneNoTraffic\n"));
mPruningNoTraffic = true;
return PostEvent(&nsHttpConnectionMgr::OnMsgPruneNoTraffic);
}
nsresult
nsHttpConnectionMgr::VerifyTraffic()
{
LOG(("nsHttpConnectionMgr::VerifyTraffic\n"));
return PostEvent(&nsHttpConnectionMgr::OnMsgVerifyTraffic);
}
nsresult
nsHttpConnectionMgr::DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *aCI)
{
@ -1032,53 +1010,6 @@ nsHttpConnectionMgr::PruneDeadConnectionsCB(const nsACString &key,
return PL_DHASH_NEXT;
}
PLDHashOperator
nsHttpConnectionMgr::VerifyTrafficCB(const nsACString &key,
nsAutoPtr<nsConnectionEntry> &ent,
void *closure)
{
// Iterate over all active connections and check them
for (uint32_t index = 0; index < ent->mActiveConns.Length(); ++index) {
nsHttpConnection *conn = ent->mActiveConns[index];
conn->CheckForTraffic(true);
}
// Iterate the idle connections and unmark them for traffic checks
for (uint32_t index = 0; index < ent->mIdleConns.Length(); ++index) {
nsHttpConnection *conn = ent->mIdleConns[index];
conn->CheckForTraffic(false);
}
return PL_DHASH_NEXT;
}
PLDHashOperator
nsHttpConnectionMgr::PruneNoTrafficCB(const nsACString &key,
nsAutoPtr<nsConnectionEntry> &ent,
void *closure)
{
// Close the connections with no registered traffic
nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
LOG((" pruning no traffic [ci=%s]\n", ent->mConnInfo->HashKey().get()));
uint32_t numConns = ent->mActiveConns.Length();
if (numConns) {
// walk the list backwards to allow us to remove entries easily
for (int index = numConns-1; index >= 0; index--) {
if (ent->mActiveConns[index]->NoTraffic()) {
nsRefPtr<nsHttpConnection> conn = dont_AddRef(ent->mActiveConns[index]);
ent->mActiveConns.RemoveElementAt(index);
self->DecrementActiveConnCount(conn);
conn->Close(NS_ERROR_ABORT);
LOG((" closed active connection due to no traffic [conn=%p]\n",
conn.get()));
}
}
}
return PL_DHASH_NEXT;
}
PLDHashOperator
nsHttpConnectionMgr::ShutdownPassCB(const nsACString &key,
nsAutoPtr<nsConnectionEntry> &ent,
@ -2283,10 +2214,6 @@ nsHttpConnectionMgr::OnMsgShutdown(int32_t, void *param)
mTimer->Cancel();
mTimer = nullptr;
}
if (mTrafficTimer) {
mTrafficTimer->Cancel();
mTrafficTimer = nullptr;
}
// signal shutdown complete
nsRefPtr<nsIRunnable> runnable =
@ -2475,50 +2402,6 @@ nsHttpConnectionMgr::OnMsgPruneDeadConnections(int32_t, void *)
mCT.Enumerate(PruneDeadConnectionsCB, this);
}
void
nsHttpConnectionMgr::OnMsgPruneNoTraffic(int32_t, void *)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
LOG(("nsHttpConnectionMgr::OnMsgPruneNoTraffic\n"));
// Prune connections without traffic
mCT.Enumerate(PruneNoTrafficCB, this);
mPruningNoTraffic = false; // not pruning anymore
}
void
nsHttpConnectionMgr::OnMsgVerifyTraffic(int32_t, void *)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
LOG(("nsHttpConnectionMgr::OnMsgVerifyTraffic\n"));
if (mPruningNoTraffic) {
// Called in the time gap when the timeout to prune notraffic
// connections has triggered but the pruning hasn't happened yet.
return;
}
// Mark connections for traffic verification
mCT.Enumerate(VerifyTrafficCB, this);
// If the timer is already there. we just re-init it
if(!mTrafficTimer) {
mTrafficTimer = do_CreateInstance("@mozilla.org/timer;1");
}
// failure to create a timer is not a fatal error, but dead
// connections will not be cleaned up as nicely
if (mTrafficTimer) {
// Give active connections time to get more traffic before killing
// them off. Default: 5000 milliseconds
mTrafficTimer->Init(this, gHttpHandler->NetworkChangedTimeout(),
nsITimer::TYPE_ONE_SHOT);
} else {
NS_WARNING("failed to create timer for VerifyTraffic!");
}
}
void
nsHttpConnectionMgr::OnMsgDoShiftReloadConnectionCleanup(int32_t, void *param)
{

View File

@ -90,14 +90,6 @@ public:
// connections.
nsresult PruneDeadConnections();
// called to close active connections with no registered "traffic"
nsresult PruneNoTraffic();
// "VerifyTraffic" means marking connections now, and then check again in
// N seconds to see if there's been any traffic and if not, kill
// that connection.
nsresult VerifyTraffic();
// Close all idle persistent connections and prevent any active connections
// from being reused. Optional connection info resets CI specific
// information such as Happy Eyeballs history.
@ -251,9 +243,6 @@ public:
uint16_t MaxRequestDelay() { return mMaxRequestDelay; }
// public, so that the SPDY/http2 seesions can activate
void ActivateTimeoutTick();
private:
virtual ~nsHttpConnectionMgr();
@ -536,8 +525,6 @@ private:
static PLDHashOperator PurgeExcessIdleConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
static PLDHashOperator PurgeExcessSpdyConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
static PLDHashOperator ClosePersistentConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
static PLDHashOperator VerifyTrafficCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
static PLDHashOperator PruneNoTrafficCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
bool ProcessPendingQForEntry(nsConnectionEntry *, bool considerAll);
bool IsUnderPressure(nsConnectionEntry *ent,
nsHttpTransaction::Classifier classification);
@ -656,8 +643,6 @@ private:
void OnMsgProcessFeedback (int32_t, void *);
void OnMsgProcessAllSpdyPendingQ (int32_t, void *);
void OnMsgUpdateRequestTokenBucket (int32_t, void *);
void OnMsgVerifyTraffic (int32_t, void *);
void OnMsgPruneNoTraffic (int32_t, void *);
// Total number of active connections in all of the ConnectionEntry objects
// that are accessed from mCT connection table.
@ -675,9 +660,6 @@ private:
uint64_t mTimeOfNextWakeUp;
// Timer for next pruning of dead connections.
nsCOMPtr<nsITimer> mTimer;
// Timer for pruning stalled connections after changed network.
nsCOMPtr<nsITimer> mTrafficTimer;
bool mPruningNoTraffic;
// A 1s tick to call nsHttpConnection::ReadTimeoutTick on
// active http/1 connections and check for orphaned half opens.
@ -703,6 +685,7 @@ private:
void *aArg);
// Read Timeout Tick handlers
void ActivateTimeoutTick();
void TimeoutTick();
static PLDHashOperator TimeoutTickCB(const nsACString &key,
nsAutoPtr<nsConnectionEntry> &ent,

View File

@ -47,7 +47,6 @@
#include "SpdyZlibReporter.h"
#include "nsIMemoryReporter.h"
#include "nsIParentalControlsService.h"
#include "nsINetworkLinkService.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/Telemetry.h"
@ -144,7 +143,6 @@ nsHttpHandler::nsHttpHandler()
, mSpdyTimeout(PR_SecondsToInterval(180))
, mResponseTimeout(PR_SecondsToInterval(300))
, mResponseTimeoutEnabled(false)
, mNetworkChangedTimeout(5000)
, mMaxRequestAttempts(10)
, mMaxRequestDelay(10)
, mIdleSynTimeout(250)
@ -349,7 +347,6 @@ nsHttpHandler::Init()
mObserverService->AddObserver(this, "net:failed-to-process-uri-content", true);
mObserverService->AddObserver(this, "last-pb-context-exited", true);
mObserverService->AddObserver(this, "browser:purge-session-history", true);
mObserverService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
}
MakeNewRequestTokenBucket();
@ -860,12 +857,6 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
mResponseTimeout = PR_SecondsToInterval(clamped(val, 0, 0xffff));
}
if (PREF_CHANGED(HTTP_PREF("network-changed.timeout"))) {
rv = prefs->GetIntPref(HTTP_PREF("network-changed.timeout"), &val);
if (NS_SUCCEEDED(rv))
mNetworkChangedTimeout = clamped(val, 1, 600) * 1000;
}
if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
if (NS_SUCCEEDED(rv)) {
@ -1786,8 +1777,9 @@ nsHttpHandler::Observe(nsISupports *subject,
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
if (prefBranch)
PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
} else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
}
else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
mHandlerActive = false;
@ -1807,25 +1799,30 @@ nsHttpHandler::Observe(nsISupports *subject,
if (!mDoNotTrackEnabled) {
Telemetry::Accumulate(Telemetry::DNT_USAGE, DONOTTRACK_VALUE_UNSET);
} else {
}
else {
Telemetry::Accumulate(Telemetry::DNT_USAGE, mDoNotTrackValue);
}
} else if (strcmp(topic, "profile-change-net-restore") == 0) {
}
else if (strcmp(topic, "profile-change-net-restore") == 0) {
// initialize connection manager
InitConnectionMgr();
} else if (strcmp(topic, "net:clear-active-logins") == 0) {
}
else if (strcmp(topic, "net:clear-active-logins") == 0) {
mAuthCache.ClearAll();
mPrivateAuthCache.ClearAll();
} else if (strcmp(topic, "net:prune-dead-connections") == 0) {
}
else if (strcmp(topic, "net:prune-dead-connections") == 0) {
if (mConnMgr) {
mConnMgr->PruneDeadConnections();
}
} else if (strcmp(topic, "net:failed-to-process-uri-content") == 0) {
}
else if (strcmp(topic, "net:failed-to-process-uri-content") == 0) {
nsCOMPtr<nsIURI> uri = do_QueryInterface(subject);
if (uri && mConnMgr) {
if (uri && mConnMgr)
mConnMgr->ReportFailedToProcess(uri);
}
} else if (strcmp(topic, "last-pb-context-exited") == 0) {
}
else if (strcmp(topic, "last-pb-context-exited") == 0) {
mPrivateAuthCache.ClearAll();
} else if (strcmp(topic, "browser:purge-session-history") == 0) {
if (mConnMgr && gSocketTransportService) {
@ -1833,15 +1830,6 @@ nsHttpHandler::Observe(nsISupports *subject,
&nsHttpConnectionMgr::ClearConnectionHistory);
gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
}
} else if (strcmp(topic, NS_NETWORK_LINK_TOPIC) == 0) {
nsCString converted = NS_ConvertUTF16toUTF8(data);
const char *state = converted.get();
if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED) == 0) {
if (mConnMgr) {
mConnMgr->PruneDeadConnections();
mConnMgr->VerifyTraffic();
}
}
}
return NS_OK;

View File

@ -79,7 +79,6 @@ public:
return mResponseTimeoutEnabled ? mResponseTimeout : 0;
}
PRIntervalTime ResponseTimeoutEnabled() { return mResponseTimeoutEnabled; }
uint32_t NetworkChangedTimeout() { return mNetworkChangedTimeout; }
uint16_t MaxRequestAttempts() { return mMaxRequestAttempts; }
const char *DefaultSocketType() { return mDefaultSocketType.get(); /* ok to return null */ }
uint32_t PhishyUserPassLength() { return mPhishyUserPassLength; }
@ -358,7 +357,7 @@ private:
PRIntervalTime mSpdyTimeout;
PRIntervalTime mResponseTimeout;
bool mResponseTimeoutEnabled;
uint32_t mNetworkChangedTimeout; // milliseconds
uint16_t mMaxRequestAttempts;
uint16_t mMaxRequestDelay;
uint16_t mIdleSynTimeout;

View File

@ -24,7 +24,6 @@ BaseWebSocketChannel::BaseWebSocketChannel()
, mWasOpened(0)
, mClientSetPingInterval(0)
, mClientSetPingTimeout(0)
, mPingForced(0)
, mPingInterval(0)
, mPingResponseTimeout(10000)
{

View File

@ -69,7 +69,6 @@ class BaseWebSocketChannel : public nsIWebSocketChannel,
uint32_t mWasOpened : 1;
uint32_t mClientSetPingInterval : 1;
uint32_t mClientSetPingTimeout : 1;
uint32_t mPingForced : 1;
uint32_t mPingInterval; /* milliseconds */
uint32_t mPingResponseTimeout; /* milliseconds */

View File

@ -35,8 +35,6 @@
#include "nsIRandomGenerator.h"
#include "nsISocketTransport.h"
#include "nsThreadUtils.h"
#include "nsINetworkLinkService.h"
#include "nsIObserverService.h"
#include "nsAutoPtr.h"
#include "nsNetCID.h"
@ -87,8 +85,7 @@ NS_IMPL_ISUPPORTS(WebSocketChannel,
nsIProtocolProxyCallback,
nsIInterfaceRequestor,
nsIChannelEventSink,
nsIThreadRetargetableRequest,
nsIObserver)
nsIThreadRetargetableRequest)
// We implement RFC 6455, which uses Sec-WebSocket-Version: 13 on the wire.
#define SEC_WEBSOCKET_VERSION "13"
@ -1049,16 +1046,6 @@ WebSocketChannel::WebSocketChannel() :
LOG(("Failed to initiate dashboard service."));
mSerial = sSerialSeed++;
// Register for prefs change notifications
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
} else {
NS_WARNING("failed to get observer service");
}
}
WebSocketChannel::~WebSocketChannel()
@ -1117,55 +1104,6 @@ WebSocketChannel::~WebSocketChannel()
}
}
NS_IMETHODIMP
WebSocketChannel::Observe(nsISupports *subject,
const char *topic,
const char16_t *data)
{
LOG(("WebSocketChannel::Observe [topic=\"%s\"]\n", topic));
if (strcmp(topic, NS_NETWORK_LINK_TOPIC) == 0) {
nsCString converted = NS_ConvertUTF16toUTF8(data);
const char *state = converted.get();
if (strcmp(state, NS_NETWORK_LINK_DATA_CHANGED) == 0) {
LOG(("WebSocket: received network CHANGED event"));
if (mPingOutstanding) {
// If there's an outstanding ping that's expected to get a pong back
// we let that do its thing.
LOG(("WebSocket: pong already pending"));
} else if (!mSocketThread) {
// there has not been an asyncopen yet on the object and then we need
// no ping.
LOG(("WebSocket: early object, no ping needed"));
} else {
LOG(("nsWebSocketChannel:: Generating Ping as network changed\n"));
if (mPingForced) {
// avoid more than one
return NS_OK;
}
if (!mPingTimer) {
// The ping timer is only conditionally running already. If it
// wasn't already created do it here.
nsresult rv;
mPingTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
if (NS_FAILED(rv)) {
NS_WARNING("unable to create ping timer. Carrying on.");
} else {
mPingTimer->SetTarget(mSocketThread);
}
}
// Trigger the ping timeout asap to fire off a new ping. Wait just
// a little bit to better avoid multi-triggers.
mPingForced = 1;
mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT);
}
}
}
return NS_OK;
}
void
WebSocketChannel::Shutdown()
{
@ -2685,16 +2623,11 @@ WebSocketChannel::Notify(nsITimer *timer)
}
if (!mPingOutstanding) {
// Allow for the case where a PING was force-sent even though ping
// interval isn't enabled. Only issue a new PING if it truly is enabled.
if (mPingInterval || mPingForced) {
LOG(("nsWebSocketChannel:: Generating Ping\n"));
mPingOutstanding = 1;
mPingForced = 0;
GeneratePing();
mPingTimer->InitWithCallback(this, mPingResponseTimeout,
nsITimer::TYPE_ONE_SHOT);
}
LOG(("nsWebSocketChannel:: Generating Ping\n"));
mPingOutstanding = 1;
GeneratePing();
mPingTimer->InitWithCallback(this, mPingResponseTimeout,
nsITimer::TYPE_ONE_SHOT);
} else {
LOG(("nsWebSocketChannel:: Timed out Ping\n"));
mPingTimer = nullptr;

View File

@ -14,7 +14,6 @@
#include "nsIAsyncOutputStream.h"
#include "nsITimer.h"
#include "nsIDNSListener.h"
#include "nsIObserver.h"
#include "nsIProtocolProxyCallback.h"
#include "nsIChannelEventSink.h"
#include "nsIHttpChannelInternal.h"
@ -63,7 +62,6 @@ class WebSocketChannel : public BaseWebSocketChannel,
public nsIOutputStreamCallback,
public nsITimerCallback,
public nsIDNSListener,
public nsIObserver,
public nsIProtocolProxyCallback,
public nsIInterfaceRequestor,
public nsIChannelEventSink
@ -80,7 +78,6 @@ public:
NS_DECL_NSIPROTOCOLPROXYCALLBACK
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIOBSERVER
// nsIWebSocketChannel methods BaseWebSocketChannel didn't implement for us
//
@ -163,8 +160,8 @@ private:
inline void ResetPingTimer()
{
mPingOutstanding = 0;
if (mPingTimer) {
mPingOutstanding = 0;
mPingTimer->SetDelay(mPingInterval);
}
}

View File

@ -12,11 +12,6 @@
#include <ole2.h>
#include <netcon.h>
#include <objbase.h>
#include <winsock2.h>
#include <ws2ipdef.h>
#include <tcpmib.h>
#include <iphlpapi.h>
#include <netioapi.h>
#include <iprtrmib.h>
#include "plstr.h"
#include "nsThreadUtils.h"
@ -27,38 +22,13 @@
#include "nsAutoPtr.h"
#include "mozilla/Services.h"
#include "nsCRT.h"
#include "mozilla/Preferences.h"
#include <iptypes.h>
#include <iphlpapi.h>
using namespace mozilla;
static HMODULE sNetshell;
static decltype(NcFreeNetconProperties)* sNcFreeNetconProperties;
static HMODULE sIphlpapi;
static decltype(NotifyIpInterfaceChange)* sNotifyIpInterfaceChange;
static decltype(CancelMibChangeNotify2)* sCancelMibChangeNotify2;
#define NETWORK_NOTIFY_CHANGED_PREF "network.notify.changed"
static void InitIphlpapi(void)
{
if (!sIphlpapi) {
sIphlpapi = LoadLibraryW(L"Iphlpapi.dll");
if (sIphlpapi) {
sNotifyIpInterfaceChange = (decltype(NotifyIpInterfaceChange)*)
GetProcAddress(sIphlpapi, "NotifyIpInterfaceChange");
sCancelMibChangeNotify2 = (decltype(CancelMibChangeNotify2)*)
GetProcAddress(sIphlpapi, "CancelMibChangeNotify2");
} else {
NS_WARNING("Failed to load Iphlpapi.dll - cannot detect network"
" changes!");
}
}
}
static void InitNetshellLibrary(void)
{
if (!sNetshell) {
@ -77,12 +47,6 @@ static void FreeDynamicLibraries(void)
FreeLibrary(sNetshell);
sNetshell = nullptr;
}
if (sIphlpapi) {
sNotifyIpInterfaceChange = nullptr;
sCancelMibChangeNotify2 = nullptr;
FreeLibrary(sIphlpapi);
sIphlpapi = nullptr;
}
}
NS_IMPL_ISUPPORTS(nsNotifyAddrListener,
@ -95,9 +59,7 @@ nsNotifyAddrListener::nsNotifyAddrListener()
, mStatusKnown(false)
, mCheckAttempted(false)
, mShutdownEvent(nullptr)
, mAllowChangedEvent(true)
{
InitIphlpapi();
}
nsNotifyAddrListener::~nsNotifyAddrListener()
@ -135,62 +97,36 @@ nsNotifyAddrListener::GetLinkType(uint32_t *aLinkType)
return NS_OK;
}
// Static Callback function for NotifyIpInterfaceChange API.
static void WINAPI OnInterfaceChange(PVOID callerContext,
PMIB_IPINTERFACE_ROW row,
MIB_NOTIFICATION_TYPE notificationType)
{
nsNotifyAddrListener *notify = static_cast<nsNotifyAddrListener*>(callerContext);
notify->CheckLinkStatus();
}
NS_IMETHODIMP
nsNotifyAddrListener::Run()
{
PR_SetCurrentThreadName("Link Monitor");
if (!sNotifyIpInterfaceChange || !sCancelMibChangeNotify2) {
// For Windows versions which are older than Vista which lack
// NotifyIpInterfaceChange. Note this means no IPv6 support.
HANDLE ev = CreateEvent(nullptr, FALSE, FALSE, nullptr);
NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY);
HANDLE handles[2] = { ev, mShutdownEvent };
OVERLAPPED overlapped = { 0 };
bool shuttingDown = false;
HANDLE ev = CreateEvent(nullptr, FALSE, FALSE, nullptr);
NS_ENSURE_TRUE(ev, NS_ERROR_OUT_OF_MEMORY);
overlapped.hEvent = ev;
while (!shuttingDown) {
HANDLE h;
DWORD ret = NotifyAddrChange(&h, &overlapped);
HANDLE handles[2] = { ev, mShutdownEvent };
OVERLAPPED overlapped = { 0 };
bool shuttingDown = false;
if (ret == ERROR_IO_PENDING) {
ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (ret == WAIT_OBJECT_0) {
CheckLinkStatus();
} else {
shuttingDown = true;
}
overlapped.hEvent = ev;
while (!shuttingDown) {
HANDLE h;
DWORD ret = NotifyAddrChange(&h, &overlapped);
if (ret == ERROR_IO_PENDING) {
ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (ret == WAIT_OBJECT_0) {
CheckLinkStatus();
} else {
shuttingDown = true;
}
} else {
shuttingDown = true;
}
CloseHandle(ev);
} else {
// Windows Vista and newer versions.
HANDLE interfacechange;
// The callback will simply invoke CheckLinkStatus()
DWORD ret = sNotifyIpInterfaceChange(
AF_UNSPEC, // IPv4 and IPv6
(PIPINTERFACE_CHANGE_CALLBACK)OnInterfaceChange,
this, // pass to callback
false, // no initial notification
&interfacechange);
if (ret == NO_ERROR) {
ret = WaitForSingleObject(mShutdownEvent, INFINITE);
}
sCancelMibChangeNotify2(interfacechange);
}
CloseHandle(ev);
return NS_OK;
}
@ -217,9 +153,6 @@ nsNotifyAddrListener::Init(void)
false);
NS_ENSURE_SUCCESS(rv, rv);
Preferences::AddBoolVarCache(&mAllowChangedEvent,
NETWORK_NOTIFY_CHANGED_PREF, true);
mShutdownEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
NS_ENSURE_TRUE(mShutdownEvent, NS_ERROR_OUT_OF_MEMORY);
@ -256,11 +189,11 @@ nsNotifyAddrListener::Shutdown(void)
return rv;
}
/* Sends the given event. Assumes aEventID never goes out of scope (static
* strings are ideal).
/* Sends the given event to the UI thread. Assumes aEventID never goes out
* of scope (static strings are ideal).
*/
nsresult
nsNotifyAddrListener::SendEvent(const char *aEventID)
nsNotifyAddrListener::SendEventToUI(const char *aEventID)
{
if (!aEventID)
return NS_ERROR_NULL_POINTER;
@ -284,12 +217,8 @@ nsNotifyAddrListener::ChangeEvent::Run()
return NS_OK;
}
// Bug 465158 features an explanation for this check. ICS being "Internet
// Connection Sharing). The description says it is always IP address
// 192.168.0.1 for this case.
bool
nsNotifyAddrListener::CheckICSGateway(PIP_ADAPTER_ADDRESSES aAdapter)
nsNotifyAddrListener::CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter)
{
if (!aAdapter->FirstUnicastAddress)
return false;
@ -391,70 +320,38 @@ nsNotifyAddrListener::CheckAdaptersAddresses(void)
{
ULONG len = 16384;
PIP_ADAPTER_ADDRESSES adapterList = (PIP_ADAPTER_ADDRESSES) moz_xmalloc(len);
PIP_ADAPTER_ADDRESSES addresses = (PIP_ADAPTER_ADDRESSES) malloc(len);
if (!addresses)
return ERROR_OUTOFMEMORY;
ULONG flags = GAA_FLAG_SKIP_DNS_SERVER|GAA_FLAG_SKIP_MULTICAST|
GAA_FLAG_SKIP_ANYCAST;
DWORD ret = GetAdaptersAddresses(AF_UNSPEC, flags, nullptr, adapterList, &len);
DWORD ret = GetAdaptersAddresses(AF_UNSPEC, 0, nullptr, addresses, &len);
if (ret == ERROR_BUFFER_OVERFLOW) {
free(adapterList);
adapterList = static_cast<PIP_ADAPTER_ADDRESSES> (moz_xmalloc(len));
ret = GetAdaptersAddresses(AF_UNSPEC, flags, nullptr, adapterList, &len);
free(addresses);
addresses = (PIP_ADAPTER_ADDRESSES) malloc(len);
if (!addresses)
return ERROR_BUFFER_OVERFLOW;
ret = GetAdaptersAddresses(AF_UNSPEC, 0, nullptr, addresses, &len);
}
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
free(adapterList);
free(addresses);
return ERROR_NOT_SUPPORTED;
}
//
// Since NotifyIpInterfaceChange() signals a change more often than we
// think is a worthy change, we checksum the entire state of all interfaces
// that are UP. If the checksum is the same as previous check, nothing
// of interest changed!
//
ULONG sum = 0;
if (ret == ERROR_SUCCESS) {
PIP_ADAPTER_ADDRESSES ptr;
bool linkUp = false;
for (PIP_ADAPTER_ADDRESSES adapter = adapterList; adapter;
adapter = adapter->Next) {
if (adapter->OperStatus != IfOperStatusUp ||
!adapter->FirstUnicastAddress ||
adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK ||
CheckICSGateway(adapter) ) {
continue;
}
// Add chars from AdapterName to the checksum.
for (int i = 0; adapter->AdapterName[i]; ++i) {
sum <<= 2;
sum += adapter->AdapterName[i];
}
// Add bytes from each socket address to the checksum.
for (PIP_ADAPTER_UNICAST_ADDRESS pip = adapter->FirstUnicastAddress;
pip; pip = pip->Next) {
SOCKET_ADDRESS *sockAddr = &pip->Address;
for (int i = 0; i < sockAddr->iSockaddrLength; ++i) {
sum += (reinterpret_cast<unsigned char *>
(sockAddr->lpSockaddr))[i];
}
}
linkUp = true;
for (ptr = addresses; !linkUp && ptr; ptr = ptr->Next) {
if (ptr->OperStatus == IfOperStatusUp &&
ptr->IfType != IF_TYPE_SOFTWARE_LOOPBACK &&
!CheckIsGateway(ptr))
linkUp = true;
}
mLinkUp = linkUp;
mStatusKnown = true;
}
free(adapterList);
if (mLinkUp) {
/* Store the checksum only if one or more interfaces are up */
mIPInterfaceChecksum = sum;
}
free(addresses);
CoUninitialize();
@ -471,47 +368,24 @@ nsNotifyAddrListener::CheckLinkStatus(void)
{
DWORD ret;
const char *event;
bool prevLinkUp = mLinkUp;
ULONG prevCsum = mIPInterfaceChecksum;
// The CheckAdaptersAddresses call is very expensive (~650 milliseconds),
// so we don't want to call it synchronously. Instead, we just start up
// assuming we have a network link, but we'll report that the status is
// unknown.
// This call is very expensive (~650 milliseconds), so we don't want to
// call it synchronously. Instead, we just start up assuming we have a
// network link, but we'll report that the status is unknown.
if (NS_IsMainThread()) {
NS_WARNING("CheckLinkStatus called on main thread! No check "
"performed. Assuming link is up, status is unknown.");
mLinkUp = true;
if (!mStatusKnown) {
event = NS_NETWORK_LINK_DATA_UNKNOWN;
} else if (!prevLinkUp) {
event = NS_NETWORK_LINK_DATA_UP;
} else {
// Known status and it was already UP
event = nullptr;
}
if (event) {
SendEvent(event);
}
} else {
ret = CheckAdaptersAddresses();
if (ret != ERROR_SUCCESS) {
mLinkUp = true;
}
if (mLinkUp && (prevCsum != mIPInterfaceChecksum)) {
// Network is online. Topology has changed. Always send CHANGED
// before UP - if allowed to.
if (mAllowChangedEvent) {
SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
}
}
if (prevLinkUp != mLinkUp) {
// UP/DOWN status changed, send appropriate UP/DOWN event
SendEvent(mLinkUp ?
NS_NETWORK_LINK_DATA_UP : NS_NETWORK_LINK_DATA_DOWN);
}
}
if (mStatusKnown)
event = mLinkUp ? NS_NETWORK_LINK_DATA_UP : NS_NETWORK_LINK_DATA_DOWN;
else
event = NS_NETWORK_LINK_DATA_UNKNOWN;
SendEventToUI(event);
}

View File

@ -30,7 +30,6 @@ public:
nsNotifyAddrListener();
nsresult Init(void);
void CheckLinkStatus(void);
protected:
class ChangeEvent : public nsRunnable {
@ -49,25 +48,16 @@ protected:
bool mCheckAttempted;
nsresult Shutdown(void);
nsresult SendEvent(const char *aEventID);
nsresult SendEventToUI(const char *aEventID);
DWORD CheckAdaptersAddresses(void);
// Checks for an Internet Connection Sharing (ICS) gateway.
bool CheckICSGateway(PIP_ADAPTER_ADDRESSES aAdapter);
bool CheckIsGateway(PIP_ADAPTER_ADDRESSES aAdapter);
bool CheckICSStatus(PWCHAR aAdapterName);
void CheckLinkStatus(void);
nsCOMPtr<nsIThread> mThread;
HANDLE mShutdownEvent;
private:
// This is a checksum of various meta data for all network interfaces
// considered UP at last check.
ULONG mIPInterfaceChecksum;
// Network changed events are enabled
bool mAllowChangedEvent;
};
#endif /* NSNOTIFYADDRLISTENER_H_ */

View File

@ -42,12 +42,6 @@ function test_sockets(serverSocket) {
}
function run_test() {
var ps = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
// disable network changed events to avoid the the risk of having the dns
// cache getting flushed behind our back
ps.setBoolPref("network.notify.changed", false);
let serverSocket = Components.classes["@mozilla.org/network/server-socket;1"]
.createInstance(Ci.nsIServerSocket);
serverSocket.init(-1, true, -1);

View File

@ -36,9 +36,6 @@ function run_test()
"function FindProxyForURL(url, host) {return 'PROXY a_non_existent_domain_x7x6c572v:80; PROXY localhost:" +
httpServer.identity.primaryPort + "';}"
);
// disable network changed events to avoid the the risk of having the
// proxyservice reset in the middle
prefserv.setBoolPref("network.notify.changed", false);
var chan = make_channel("http://localhost:" +
httpServer.identity.primaryPort + "/content");