gecko-dev/netwerk/protocol/http/nsHttpConnectionMgr.h
Nicholas Hurley a2d8c9ef38 Bug 1355858 - Blacklist hosts from spdy who are very poorly behaved. r=dragana
In certain cases (such as the case from bug 1050329, where a server claims to speak h2, but really doesn't), we will end up trying every connection to that server as h2 before falling back to http/1.1. Once we know a server is very badly behaved, it doesn't make sense to keep trying h2 (at least for the current browsing session). This adds an in-memory blacklist of origins & conninfos to not try h2 on, so we don't waste round trips trying h2, failing, and then dialing back with http/1.1 except for the first connection to an origin.

Depends on D8436

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

--HG--
extra : moz-landing-system : lando
2018-10-25 20:52:59 +00:00

828 lines
36 KiB
C++

/* vim:set ts=4 sw=4 sts=4 et cin: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsHttpConnectionMgr_h__
#define nsHttpConnectionMgr_h__
#include "nsHttpConnection.h"
#include "nsHttpTransaction.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "nsAutoPtr.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Attributes.h"
#include "AlternateServices.h"
#include "ARefBase.h"
#include "nsWeakReference.h"
#include "TCPFastOpen.h"
#include "nsINamed.h"
#include "nsIObserver.h"
#include "nsITimer.h"
class nsIHttpUpgradeListener;
namespace mozilla {
namespace net {
class EventTokenBucket;
class NullHttpTransaction;
struct HttpRetParams;
// 8d411b53-54bc-4a99-8b78-ff125eab1564
#define NS_HALFOPENSOCKET_IID \
{ 0x8d411b53, 0x54bc, 0x4a99, {0x8b, 0x78, 0xff, 0x12, 0x5e, 0xab, 0x15, 0x64 }}
//-----------------------------------------------------------------------------
// message handlers have this signature
class nsHttpConnectionMgr;
typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(int32_t, ARefBase *);
class nsHttpConnectionMgr final : public nsIObserver
, public AltSvcCache
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
// parameter names
enum nsParamName {
MAX_URGENT_START_Q,
MAX_CONNECTIONS,
MAX_PERSISTENT_CONNECTIONS_PER_HOST,
MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
MAX_REQUEST_DELAY,
THROTTLING_ENABLED,
THROTTLING_SUSPEND_FOR,
THROTTLING_RESUME_FOR,
THROTTLING_READ_LIMIT,
THROTTLING_READ_INTERVAL,
THROTTLING_HOLD_TIME,
THROTTLING_MAX_TIME
};
//-------------------------------------------------------------------------
// NOTE: functions below may only be called on the main thread.
//-------------------------------------------------------------------------
nsHttpConnectionMgr();
MOZ_MUST_USE nsresult Init(uint16_t maxUrgentExcessiveConns,
uint16_t maxConnections,
uint16_t maxPersistentConnectionsPerHost,
uint16_t maxPersistentConnectionsPerProxy,
uint16_t maxRequestDelay,
bool throttleEnabled,
uint32_t throttleVersion,
uint32_t throttleSuspendFor,
uint32_t throttleResumeFor,
uint32_t throttleReadLimit,
uint32_t throttleReadInterval,
uint32_t throttleHoldTime,
uint32_t throttleMaxTime);
MOZ_MUST_USE nsresult Shutdown();
//-------------------------------------------------------------------------
// NOTE: functions below may be called on any thread.
//-------------------------------------------------------------------------
// Schedules next pruning of dead connection to happen after
// given time.
void PruneDeadConnectionsAfter(uint32_t time);
// this cancels all outstanding transactions but does not shut down the mgr
void AbortAndCloseAllConnections(int32_t, ARefBase *);
// Stops timer scheduled for next pruning of dead connections if
// there are no more idle connections or active spdy ones
void ConditionallyStopPruneDeadConnectionsTimer();
// Stops timer used for the read timeout tick if there are no currently
// active connections.
void ConditionallyStopTimeoutTick();
// adds a transaction to the list of managed transactions.
MOZ_MUST_USE nsresult AddTransaction(nsHttpTransaction *, int32_t priority);
// called to reschedule the given transaction. it must already have been
// added to the connection manager via AddTransaction.
MOZ_MUST_USE nsresult RescheduleTransaction(nsHttpTransaction *,
int32_t priority);
// TOOD
void UpdateClassOfServiceOnTransaction(nsHttpTransaction *,
uint32_t classOfService);
// cancels a transaction w/ the given reason.
MOZ_MUST_USE nsresult CancelTransaction(nsHttpTransaction *,
nsresult reason);
MOZ_MUST_USE nsresult CancelTransactions(nsHttpConnectionInfo *,
nsresult reason);
// called to force the connection manager to prune its list of idle
// connections.
MOZ_MUST_USE nsresult PruneDeadConnections();
// called to close active connections with no registered "traffic"
MOZ_MUST_USE 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.
MOZ_MUST_USE 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.
MOZ_MUST_USE nsresult DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *);
// called to get a reference to the socket transport service. the socket
// transport service is not available when the connection manager is down.
MOZ_MUST_USE nsresult GetSocketThreadTarget(nsIEventTarget **);
// called to indicate a transaction for the connectionInfo is likely coming
// soon. The connection manager may use this information to start a TCP
// and/or SSL level handshake for that resource immediately so that it is
// ready when the transaction is submitted. No obligation is taken on by the
// connection manager, nor is the submitter obligated to actually submit a
// real transaction for this connectionInfo.
MOZ_MUST_USE nsresult SpeculativeConnect(nsHttpConnectionInfo *,
nsIInterfaceRequestor *,
uint32_t caps = 0,
NullHttpTransaction * = nullptr);
// called when a connection is done processing a transaction. if the
// connection can be reused then it will be added to the idle list, else
// it will be closed.
MOZ_MUST_USE nsresult ReclaimConnection(nsHttpConnection *conn);
// called by the main thread to execute the taketransport() logic on the
// socket thread after a 101 response has been received and the socket
// needs to be transferred to an expectant upgrade listener such as
// websockets.
MOZ_MUST_USE nsresult
CompleteUpgrade(nsAHttpConnection *aConn,
nsIHttpUpgradeListener *aUpgradeListener);
// called to update a parameter after the connection manager has already
// been initialized.
MOZ_MUST_USE nsresult UpdateParam(nsParamName name, uint16_t value);
// called from main thread to post a new request token bucket
// to the socket thread
MOZ_MUST_USE nsresult UpdateRequestTokenBucket(EventTokenBucket *aBucket);
// clears the connection history mCT
MOZ_MUST_USE nsresult ClearConnectionHistory();
void ReportFailedToProcess(nsIURI *uri);
// Causes a large amount of connection diagnostic information to be
// printed to the javascript console
void PrintDiagnostics();
//-------------------------------------------------------------------------
// NOTE: functions below may be called only on the socket thread.
//-------------------------------------------------------------------------
// called to change the connection entry associated with conn from specific into
// a wildcard (i.e. http2 proxy friendy) mapping
void MoveToWildCardConnEntry(nsHttpConnectionInfo *specificCI,
nsHttpConnectionInfo *wildcardCI,
nsHttpConnection *conn);
// called to force the transaction queue to be processed once more, giving
// preference to the specified connection.
MOZ_MUST_USE nsresult ProcessPendingQ(nsHttpConnectionInfo *);
MOZ_MUST_USE bool ProcessPendingQForEntry(nsHttpConnectionInfo *);
// Try and process all pending transactions
MOZ_MUST_USE nsresult ProcessPendingQ();
// This is used to force an idle connection to be closed and removed from
// the idle connection list. It is called when the idle connection detects
// that the network peer has closed the transport.
MOZ_MUST_USE nsresult CloseIdleConnection(nsHttpConnection *);
MOZ_MUST_USE nsresult RemoveIdleConnection(nsHttpConnection *);
// The connection manager needs to know when a normal HTTP connection has been
// upgraded to SPDY because the dispatch and idle semantics are a little
// bit different.
void ReportSpdyConnection(nsHttpConnection *, bool usingSpdy);
bool GetConnectionData(nsTArray<HttpRetParams> *);
void ResetIPFamilyPreference(nsHttpConnectionInfo *);
uint16_t MaxRequestDelay() { return mMaxRequestDelay; }
// public, so that the SPDY/http2 seesions can activate
void ActivateTimeoutTick();
nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId);
// tracks and untracks active transactions according their throttle status
void AddActiveTransaction(nsHttpTransaction* aTrans);
void RemoveActiveTransaction(nsHttpTransaction* aTrans,
Maybe<bool> const& aOverride = Nothing());
void UpdateActiveTransaction(nsHttpTransaction* aTrans);
// called by nsHttpTransaction::WriteSegments. decides whether the transaction
// should limit reading its reponse data. There are various conditions this
// methods evaluates. If called by an active-tab non-throttled transaction,
// the throttling window time will be prolonged.
bool ShouldThrottle(nsHttpTransaction* aTrans);
// prolongs the throttling time window to now + the window preferred delay.
// called when:
// - any transaction is activated
// - or when a currently unthrottled transaction for the active window receives data
void TouchThrottlingTimeWindow(bool aEnsureTicker = true);
// return true iff the connection has pending transactions for the active tab.
// it's mainly used to disallow throttling (limit reading) of a response
// belonging to the same conn info to free up a connection ASAP.
// NOTE: relatively expensive to call, there are two hashtable lookups.
bool IsConnEntryUnderPressure(nsHttpConnectionInfo*);
uint64_t CurrentTopLevelOuterContentWindowId()
{
return mCurrentTopLevelOuterContentWindowId;
}
void BlacklistSpdy(const nsHttpConnectionInfo *ci);
private:
virtual ~nsHttpConnectionMgr();
class nsHalfOpenSocket;
class PendingTransactionInfo;
// nsConnectionEntry
//
// mCT maps connection info hash key to nsConnectionEntry object, which
// contains list of active and idle connections as well as the list of
// pending transactions.
//
class nsConnectionEntry
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsConnectionEntry)
explicit nsConnectionEntry(nsHttpConnectionInfo *ci);
RefPtr<nsHttpConnectionInfo> mConnInfo;
nsTArray<RefPtr<PendingTransactionInfo> > mUrgentStartQ;// the urgent start transaction queue
// This table provides a mapping from top level outer content window id
// to a queue of pending transaction information.
// The transaction's order in pending queue is decided by whether it's a
// blocking transaction and its priority.
// Note that the window id could be 0 if the http request
// is initialized without a window.
nsClassHashtable<nsUint64HashKey,
nsTArray<RefPtr<PendingTransactionInfo>>> mPendingTransactionTable;
nsTArray<RefPtr<nsHttpConnection> > mActiveConns; // active connections
nsTArray<RefPtr<nsHttpConnection> > mIdleConns; // idle persistent connections
nsTArray<nsHalfOpenSocket*> mHalfOpens; // half open connections
nsTArray<RefPtr<nsHalfOpenSocket> > mHalfOpenFastOpenBackups; // backup half open connections for connection in fast open phase
bool AvailableForDispatchNow();
// calculate the number of half open sockets that have not had at least 1
// connection complete
uint32_t UnconnectedHalfOpens();
// Remove a particular half open socket from the mHalfOpens array
void RemoveHalfOpen(nsHalfOpenSocket *);
// Spdy sometimes resolves the address in the socket manager in order
// to re-coalesce sharded HTTP hosts. The dotted decimal address is
// combined with the Anonymous flag and OA from the connection information
// to build the hash key for hosts in the same ip pool.
//
nsTArray<nsCString> mCoalescingKeys;
// To have the UsingSpdy flag means some host with the same connection
// entry has done NPN=spdy/* at some point. It does not mean every
// connection is currently using spdy.
bool mUsingSpdy : 1;
// Determines whether or not we can continue to use spdy-enabled
// connections in the future. This is generally set to false either when
// some connection here encounters connection-based auth (such as NTLM)
// or when some connection here encounters a server that is totally
// busted (such as it fails to properly perform the h2 handshake).
bool mCanUseSpdy : 1;
// Flags to remember our happy-eyeballs decision.
// Reset only by Ctrl-F5 reload.
// True when we've first connected an IPv4 server for this host,
// initially false.
bool mPreferIPv4 : 1;
// True when we've first connected an IPv6 server for this host,
// initially false.
bool mPreferIPv6 : 1;
// True if this connection entry has initiated a socket
bool mUsedForConnection : 1;
// Try using TCP Fast Open.
bool mUseFastOpen : 1;
bool mDoNotDestroy : 1;
bool AllowSpdy() const { return mCanUseSpdy; }
void DisallowSpdy();
// Set the IP family preference flags according the connected family
void RecordIPFamilyPreference(uint16_t family);
// Resets all flags to their default values
void ResetIPFamilyPreference();
// True iff there is currently an established IP family preference
bool PreferenceKnown() const;
// Return the count of pending transactions for all window ids.
size_t PendingQLength() const;
// Add a transaction information into the pending queue in
// |mPendingTransactionTable| according to the transaction's
// top level outer content window id.
void InsertTransaction(PendingTransactionInfo *info,
bool aInsertAsFirstForTheSamePriority = false);
// Append transactions to the |result| whose window id
// is equal to |windowId|.
// NOTE: maxCount == 0 will get all transactions in the queue.
void AppendPendingQForFocusedWindow(
uint64_t windowId,
nsTArray<RefPtr<PendingTransactionInfo>> &result,
uint32_t maxCount = 0);
// Append transactions whose window id isn't equal to |windowId|.
// NOTE: windowId == 0 will get all transactions for both
// focused and non-focused windows.
void AppendPendingQForNonFocusedWindows(
uint64_t windowId,
nsTArray<RefPtr<PendingTransactionInfo>> &result,
uint32_t maxCount = 0);
// Remove the empty pendingQ in |mPendingTransactionTable|.
void RemoveEmptyPendingQ();
private:
~nsConnectionEntry();
};
public:
static nsAHttpConnection *MakeConnectionHandle(nsHttpConnection *aWrapped);
void RegisterOriginCoalescingKey(nsHttpConnection *, const nsACString &host, int32_t port);
private:
// nsHalfOpenSocket is used to hold the state of an opening TCP socket
// while we wait for it to establish and bind it to a connection
class nsHalfOpenSocket final : public nsIOutputStreamCallback,
public nsITransportEventSink,
public nsIInterfaceRequestor,
public nsITimerCallback,
public nsINamed,
public nsSupportsWeakReference,
public TCPFastOpen
{
~nsHalfOpenSocket();
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_HALFOPENSOCKET_IID)
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOUTPUTSTREAMCALLBACK
NS_DECL_NSITRANSPORTEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSITIMERCALLBACK
NS_DECL_NSINAMED
nsHalfOpenSocket(nsConnectionEntry *ent,
nsAHttpTransaction *trans,
uint32_t caps,
bool speculative,
bool isFromPredictor,
bool urgentStart);
MOZ_MUST_USE nsresult SetupStreams(nsISocketTransport **,
nsIAsyncInputStream **,
nsIAsyncOutputStream **,
bool isBackup);
MOZ_MUST_USE nsresult SetupPrimaryStreams();
MOZ_MUST_USE nsresult SetupBackupStreams();
void SetupBackupTimer();
void CancelBackupTimer();
void Abandon();
double Duration(TimeStamp epoch);
nsISocketTransport *SocketTransport() { return mSocketTransport; }
nsISocketTransport *BackupTransport() { return mBackupTransport; }
nsAHttpTransaction *Transaction() { return mTransaction; }
bool IsSpeculative() { return mSpeculative; }
bool IsFromPredictor() { return mIsFromPredictor; }
bool Allow1918() { return mAllow1918; }
void SetAllow1918(bool val) { mAllow1918 = val; }
bool HasConnected() { return mHasConnected; }
void PrintDiagnostics(nsCString &log);
// Checks whether the transaction can be dispatched using this
// half-open's connection. If this half-open is marked as urgent-start,
// it only accepts urgent start transactions. Call only before Claim().
bool AcceptsTransaction(nsHttpTransaction* trans);
bool Claim();
void Unclaim();
bool FastOpenEnabled() override;
nsresult StartFastOpen() override;
void SetFastOpenConnected(nsresult, bool aWillRetry) override;
void FastOpenNotSupported() override;
void SetFastOpenStatus(uint8_t tfoStatus) override;
void CancelFastOpenConnection();
private:
nsresult SetupConn(nsIAsyncOutputStream *out,
bool aFastOpen);
// To find out whether |mTransaction| is still in the connection entry's
// pending queue. If the transaction is found and |removeWhenFound| is
// true, the transaction will be removed from the pending queue.
already_AddRefed<PendingTransactionInfo>
FindTransactionHelper(bool removeWhenFound);
RefPtr<nsAHttpTransaction> mTransaction;
bool mDispatchedMTransaction;
nsCOMPtr<nsISocketTransport> mSocketTransport;
nsCOMPtr<nsIAsyncOutputStream> mStreamOut;
nsCOMPtr<nsIAsyncInputStream> mStreamIn;
uint32_t mCaps;
// mSpeculative is set if the socket was created from
// SpeculativeConnect(). It is cleared when a transaction would normally
// start a new connection from scratch but instead finds this one in
// the half open list and claims it for its own use. (which due to
// the vagaries of scheduling from the pending queue might not actually
// match up - but it prevents a speculative connection from opening
// more connections that are needed.)
bool mSpeculative;
// If created with a non-null urgent transaction, remember it, so we can
// mark the connection as urgent rightaway it's created.
bool mUrgentStart;
// mIsFromPredictor is set if the socket originated from the network
// Predictor. It is used to gather telemetry data on used speculative
// connections from the predictor.
bool mIsFromPredictor;
bool mAllow1918;
TimeStamp mPrimarySynStarted;
TimeStamp mBackupSynStarted;
// mHasConnected tracks whether one of the sockets has completed the
// connection process. It may have completed unsuccessfully.
bool mHasConnected;
bool mPrimaryConnectedOK;
bool mBackupConnectedOK;
bool mBackupConnStatsSet;
// A nsHalfOpenSocket can be made for a concrete non-null transaction,
// but the transaction can be dispatch to another connection. In that
// case we can free this transaction to be claimed by other
// transactions.
bool mFreeToUse;
nsresult mPrimaryStreamStatus;
bool mFastOpenInProgress;
RefPtr<nsHttpConnection> mConnectionNegotiatingFastOpen;
uint8_t mFastOpenStatus;
RefPtr<nsConnectionEntry> mEnt;
nsCOMPtr<nsITimer> mSynTimer;
nsCOMPtr<nsISocketTransport> mBackupTransport;
nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut;
nsCOMPtr<nsIAsyncInputStream> mBackupStreamIn;
};
friend class nsHalfOpenSocket;
class PendingTransactionInfo final : public ARefBase
{
public:
explicit PendingTransactionInfo(nsHttpTransaction * trans)
: mTransaction(trans)
{}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PendingTransactionInfo, override)
void PrintDiagnostics(nsCString &log);
public: // meant to be public.
RefPtr<nsHttpTransaction> mTransaction;
nsWeakPtr mHalfOpen;
nsWeakPtr mActiveConn;
private:
virtual ~PendingTransactionInfo() = default;
};
friend class PendingTransactionInfo;
class PendingComparator
{
public:
bool Equals(const PendingTransactionInfo *aPendingTrans,
const nsAHttpTransaction *aTrans) const {
return aPendingTrans->mTransaction.get() == aTrans;
}
};
//-------------------------------------------------------------------------
// NOTE: these members may be accessed from any thread (use mReentrantMonitor)
//-------------------------------------------------------------------------
ReentrantMonitor mReentrantMonitor;
nsCOMPtr<nsIEventTarget> mSocketThreadTarget;
// connection limits
uint16_t mMaxUrgentExcessiveConns;
uint16_t mMaxConns;
uint16_t mMaxPersistConnsPerHost;
uint16_t mMaxPersistConnsPerProxy;
uint16_t mMaxRequestDelay; // in seconds
bool mThrottleEnabled;
uint32_t mThrottleVersion;
uint32_t mThrottleSuspendFor;
uint32_t mThrottleResumeFor;
uint32_t mThrottleReadLimit;
uint32_t mThrottleReadInterval;
uint32_t mThrottleHoldTime;
TimeDuration mThrottleMaxTime;
Atomic<bool, mozilla::Relaxed> mIsShuttingDown;
//-------------------------------------------------------------------------
// NOTE: these members are only accessed on the socket transport thread
//-------------------------------------------------------------------------
MOZ_MUST_USE bool ProcessPendingQForEntry(nsConnectionEntry *,
bool considerAll);
bool DispatchPendingQ(nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ,
nsConnectionEntry *ent,
bool considerAll);
// This function selects transactions from mPendingTransactionTable to dispatch
// according to the following conditions:
// 1. When ActiveTabPriority() is false, only get transactions from the queue
// whose window id is 0.
// 2. If |considerAll| is false, either get transactions from the focused window
// queue or non-focused ones.
// 3. If |considerAll| is true, fill the |pendingQ| with the transactions from
// both focused window and non-focused window queues.
void PreparePendingQForDispatching(nsConnectionEntry *ent,
nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ,
bool considerAll);
// Return total active connection count, which is the sum of
// active connections and unconnected half open connections.
uint32_t TotalActiveConnections(nsConnectionEntry *ent) const;
// Return |mMaxPersistConnsPerProxy| or |mMaxPersistConnsPerHost|,
// depending whether the proxy is used.
uint32_t MaxPersistConnections(nsConnectionEntry *ent) const;
bool AtActiveConnectionLimit(nsConnectionEntry *, uint32_t caps);
MOZ_MUST_USE nsresult TryDispatchTransaction(nsConnectionEntry *ent,
bool onlyReusedConnection,
PendingTransactionInfo *pendingTransInfo);
MOZ_MUST_USE nsresult TryDispatchTransactionOnIdleConn(nsConnectionEntry *ent,
PendingTransactionInfo *pendingTransInfo,
bool respectUrgency,
bool *allUrgent = nullptr);
MOZ_MUST_USE nsresult DispatchTransaction(nsConnectionEntry *,
nsHttpTransaction *,
nsHttpConnection *);
MOZ_MUST_USE nsresult DispatchAbstractTransaction(nsConnectionEntry *,
nsAHttpTransaction *,
uint32_t,
nsHttpConnection *,
int32_t);
bool RestrictConnections(nsConnectionEntry *);
MOZ_MUST_USE nsresult ProcessNewTransaction(nsHttpTransaction *);
MOZ_MUST_USE nsresult EnsureSocketThreadTarget();
void ClosePersistentConnections(nsConnectionEntry *ent);
void ReportProxyTelemetry(nsConnectionEntry *ent);
MOZ_MUST_USE nsresult CreateTransport(nsConnectionEntry *,
nsAHttpTransaction *, uint32_t, bool,
bool, bool, bool,
PendingTransactionInfo *pendingTransInfo);
void AddActiveConn(nsHttpConnection *, nsConnectionEntry *);
void DecrementActiveConnCount(nsHttpConnection *);
void StartedConnect();
void RecvdConnect();
// This function will unclaim the claimed connection or set a halfOpen
// socket to the speculative state if the transaction claiming them ends up
// using another connection.
void ReleaseClaimedSockets(nsConnectionEntry *ent,
PendingTransactionInfo * pendingTransInfo);
void InsertTransactionSorted(nsTArray<RefPtr<PendingTransactionInfo> > &pendingQ,
PendingTransactionInfo *pendingTransInfo,
bool aInsertAsFirstForTheSamePriority = false);
nsConnectionEntry *GetOrCreateConnectionEntry(nsHttpConnectionInfo *,
bool allowWildCard);
MOZ_MUST_USE nsresult MakeNewConnection(nsConnectionEntry *ent,
PendingTransactionInfo *pendingTransInfo);
// Manage h2 connection coalescing
// The hashtable contains arrays of weak pointers to nsHttpConnections
nsClassHashtable<nsCStringHashKey, nsTArray<nsWeakPtr> > mCoalescingHash;
nsHttpConnection *FindCoalescableConnection(nsConnectionEntry *ent, bool justKidding);
nsHttpConnection *FindCoalescableConnectionByHashKey(nsConnectionEntry *ent, const nsCString &key, bool justKidding);
void UpdateCoalescingForNewConn(nsHttpConnection *conn, nsConnectionEntry *ent);
nsHttpConnection *GetSpdyActiveConn(nsConnectionEntry *ent);
void ProcessSpdyPendingQ(nsConnectionEntry *ent);
void DispatchSpdyPendingQ(nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ,
nsConnectionEntry *ent,
nsHttpConnection *conn);
// used to marshall events to the socket transport thread.
MOZ_MUST_USE nsresult PostEvent(nsConnEventHandler handler,
int32_t iparam = 0,
ARefBase *vparam = nullptr);
// Used to close all transactions in the |pendingQ| with the given |reason|.
// Note that the |pendingQ| will be also cleared.
void CancelTransactionsHelper(
nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ,
const nsHttpConnectionInfo *ci,
const nsConnectionEntry *ent,
nsresult reason);
// message handlers
void OnMsgShutdown (int32_t, ARefBase *);
void OnMsgShutdownConfirm (int32_t, ARefBase *);
void OnMsgNewTransaction (int32_t, ARefBase *);
void OnMsgReschedTransaction (int32_t, ARefBase *);
void OnMsgUpdateClassOfServiceOnTransaction (int32_t, ARefBase *);
void OnMsgCancelTransaction (int32_t, ARefBase *);
void OnMsgCancelTransactions (int32_t, ARefBase *);
void OnMsgProcessPendingQ (int32_t, ARefBase *);
void OnMsgPruneDeadConnections (int32_t, ARefBase *);
void OnMsgSpeculativeConnect (int32_t, ARefBase *);
void OnMsgReclaimConnection (int32_t, ARefBase *);
void OnMsgCompleteUpgrade (int32_t, ARefBase *);
void OnMsgUpdateParam (int32_t, ARefBase *);
void OnMsgDoShiftReloadConnectionCleanup (int32_t, ARefBase *);
void OnMsgProcessFeedback (int32_t, ARefBase *);
void OnMsgProcessAllSpdyPendingQ (int32_t, ARefBase *);
void OnMsgUpdateRequestTokenBucket (int32_t, ARefBase *);
void OnMsgVerifyTraffic (int32_t, ARefBase *);
void OnMsgPruneNoTraffic (int32_t, ARefBase *);
void OnMsgUpdateCurrentTopLevelOuterContentWindowId (int32_t, ARefBase *);
// Total number of active connections in all of the ConnectionEntry objects
// that are accessed from mCT connection table.
uint16_t mNumActiveConns;
// Total number of idle connections in all of the ConnectionEntry objects
// that are accessed from mCT connection table.
uint16_t mNumIdleConns;
// Total number of spdy connections which are a subset of the active conns
uint16_t mNumSpdyActiveConns;
// Total number of connections in mHalfOpens ConnectionEntry objects
// that are accessed from mCT connection table
uint32_t mNumHalfOpenConns;
// Holds time in seconds for next wake-up to prune dead connections.
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.
// Disabled when there are no active or half open connections.
nsCOMPtr<nsITimer> mTimeoutTick;
bool mTimeoutTickArmed;
uint32_t mTimeoutTickNext;
//
// the connection table
//
// this table is indexed by connection key. each entry is a
// nsConnectionEntry object. It is unlocked and therefore must only
// be accessed from the socket thread.
//
nsRefPtrHashtable<nsCStringHashKey, nsConnectionEntry> mCT;
// Read Timeout Tick handlers
void TimeoutTick();
// For diagnostics
void OnMsgPrintDiagnostics(int32_t, ARefBase *);
nsCString mLogData;
uint64_t mCurrentTopLevelOuterContentWindowId;
// Called on a pref change
void SetThrottlingEnabled(bool aEnable);
// we only want to throttle for a limited amount of time after a new
// active transaction is added so that we don't block downloads on comet,
// socket and any kind of longstanding requests that don't need bandwidth.
// these methods track this time.
bool InThrottlingTimeWindow();
// Two hashtalbes keeping track of active transactions regarding window id and throttling.
// Used by the throttling algorithm to obtain number of transactions for the active tab
// and for inactive tabs according their throttle status.
// mActiveTransactions[0] are all unthrottled transactions, mActiveTransactions[1] throttled.
nsClassHashtable<nsUint64HashKey, nsTArray<RefPtr<nsHttpTransaction>>> mActiveTransactions[2];
// V1 specific
// Whether we are inside the "stop reading" interval, altered by the throttle ticker
bool mThrottlingInhibitsReading;
TimeStamp mThrottlingWindowEndsAt;
// ticker for the 'stop reading'/'resume reading' signal
nsCOMPtr<nsITimer> mThrottleTicker;
// Checks if the combination of active transactions requires the ticker.
bool IsThrottleTickerNeeded();
// The method also unschedules the delayed resume of background tabs timer
// if the ticker was about to be scheduled.
void EnsureThrottleTickerIfNeeded();
// V1:
// Drops also the mThrottlingInhibitsReading flag. Immediate or delayed resume
// of currently throttled transactions is not affected by this method.
// V2:
// Immediate or delayed resume of currently throttled transactions is not
// affected by this method.
void DestroyThrottleTicker();
// V1:
// Handler for the ticker: alters the mThrottlingInhibitsReading flag.
// V2:
// Handler for the ticker: calls ResumeReading() for all throttled transactions.
void ThrottlerTick();
// mechanism to delay immediate resume of background tabs and chrome initiated
// throttled transactions after the last transaction blocking their unthrottle
// has been removed. Needs to be delayed because during a page load there is
// a number of intervals when there is no transaction that would cause throttling.
// Hence, throttling of long standing responses, like downloads, would be mostly
// ineffective if resumed during every such interval.
nsCOMPtr<nsITimer> mDelayedResumeReadTimer;
// Schedule the resume
void DelayedResumeBackgroundThrottledTransactions();
// Simply destroys the timer
void CancelDelayedResumeBackgroundThrottledTransactions();
// Handler for the timer: resumes all background throttled transactions
void ResumeBackgroundThrottledTransactions();
// Simple helpers, iterates the given hash/array and resume.
// @param excludeActive: skip active tabid transactions.
void ResumeReadOf(nsClassHashtable<nsUint64HashKey, nsTArray<RefPtr<nsHttpTransaction>>>&,
bool excludeActive = false);
void ResumeReadOf(nsTArray<RefPtr<nsHttpTransaction>>*);
// Cached status of the active tab active transactions existence,
// saves a lot of hashtable lookups
bool mActiveTabTransactionsExist;
bool mActiveTabUnthrottledTransactionsExist;
void LogActiveTransactions(char);
nsTArray<RefPtr<PendingTransactionInfo>>*
GetTransactionPendingQHelper(nsConnectionEntry *ent, nsAHttpTransaction *trans);
// When current active tab is changed, this function uses
// |previousWindowId| to select background transactions and
// mCurrentTopLevelOuterContentWindowId| to select foreground transactions.
// Then, it notifies selected transactions' connection of the new active tab id.
void NotifyConnectionOfWindowIdChange(uint64_t previousWindowId);
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnectionMgr::nsHalfOpenSocket, NS_HALFOPENSOCKET_IID)
} // namespace net
} // namespace mozilla
#endif // !nsHttpConnectionMgr_h__