зеркало из https://github.com/mozilla/gecko-dev.git
814 строки
36 KiB
C++
814 строки
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;
|
|
}
|
|
|
|
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;
|
|
|
|
// 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;
|
|
|
|
// Set the IP family preference flags according the connected family
|
|
void RecordIPFamilyPreference(uint16_t family);
|
|
// Resets all flags to their default values
|
|
void ResetIPFamilyPreference();
|
|
|
|
// 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 : 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() {}
|
|
};
|
|
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__
|