1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,677 @@ 1.4 +/* vim:set ts=4 sw=4 sts=4 et cin: */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsHttpConnectionMgr_h__ 1.10 +#define nsHttpConnectionMgr_h__ 1.11 + 1.12 +#include "nsHttpConnection.h" 1.13 +#include "nsHttpTransaction.h" 1.14 +#include "nsTArray.h" 1.15 +#include "nsThreadUtils.h" 1.16 +#include "nsClassHashtable.h" 1.17 +#include "nsDataHashtable.h" 1.18 +#include "nsAutoPtr.h" 1.19 +#include "mozilla/ReentrantMonitor.h" 1.20 +#include "mozilla/TimeStamp.h" 1.21 +#include "mozilla/Attributes.h" 1.22 + 1.23 +#include "nsIObserver.h" 1.24 +#include "nsITimer.h" 1.25 +#include "nsIRandomGenerator.h" 1.26 + 1.27 +// We need our own optional debug define because pipelining behavior 1.28 +// is significantly altered by rendering speed (which is abysmal on 1.29 +// debug builds) 1.30 +#ifdef DEBUG 1.31 +# define WTF_DEBUG 1.32 +#endif 1.33 + 1.34 +#ifdef WTF_DEBUG 1.35 +# define WTF_TEST 1.36 +#endif 1.37 + 1.38 +class nsIHttpUpgradeListener; 1.39 + 1.40 +namespace mozilla { 1.41 +namespace net { 1.42 +class EventTokenBucket; 1.43 +struct HttpRetParams; 1.44 + 1.45 +//----------------------------------------------------------------------------- 1.46 + 1.47 +class nsHttpConnectionMgr : public nsIObserver 1.48 +{ 1.49 +public: 1.50 + NS_DECL_THREADSAFE_ISUPPORTS 1.51 + NS_DECL_NSIOBSERVER 1.52 + 1.53 + // parameter names 1.54 + enum nsParamName { 1.55 + MAX_CONNECTIONS, 1.56 + MAX_PERSISTENT_CONNECTIONS_PER_HOST, 1.57 + MAX_PERSISTENT_CONNECTIONS_PER_PROXY, 1.58 + MAX_REQUEST_DELAY, 1.59 + MAX_PIPELINED_REQUESTS, 1.60 + MAX_OPTIMISTIC_PIPELINED_REQUESTS 1.61 + }; 1.62 + 1.63 + //------------------------------------------------------------------------- 1.64 + // NOTE: functions below may only be called on the main thread. 1.65 + //------------------------------------------------------------------------- 1.66 + 1.67 + nsHttpConnectionMgr(); 1.68 + 1.69 + nsresult Init(uint16_t maxConnections, 1.70 + uint16_t maxPersistentConnectionsPerHost, 1.71 + uint16_t maxPersistentConnectionsPerProxy, 1.72 + uint16_t maxRequestDelay, 1.73 + uint16_t maxPipelinedRequests, 1.74 + uint16_t maxOptimisticPipelinedRequests); 1.75 + nsresult Shutdown(); 1.76 + 1.77 + //------------------------------------------------------------------------- 1.78 + // NOTE: functions below may be called on any thread. 1.79 + //------------------------------------------------------------------------- 1.80 + 1.81 + // Schedules next pruning of dead connection to happen after 1.82 + // given time. 1.83 + void PruneDeadConnectionsAfter(uint32_t time); 1.84 + 1.85 + // Stops timer scheduled for next pruning of dead connections if 1.86 + // there are no more idle connections or active spdy ones 1.87 + void ConditionallyStopPruneDeadConnectionsTimer(); 1.88 + 1.89 + // Stops timer used for the read timeout tick if there are no currently 1.90 + // active connections. 1.91 + void ConditionallyStopTimeoutTick(); 1.92 + 1.93 + // adds a transaction to the list of managed transactions. 1.94 + nsresult AddTransaction(nsHttpTransaction *, int32_t priority); 1.95 + 1.96 + // called to reschedule the given transaction. it must already have been 1.97 + // added to the connection manager via AddTransaction. 1.98 + nsresult RescheduleTransaction(nsHttpTransaction *, int32_t priority); 1.99 + 1.100 + // cancels a transaction w/ the given reason. 1.101 + nsresult CancelTransaction(nsHttpTransaction *, nsresult reason); 1.102 + 1.103 + // called to force the connection manager to prune its list of idle 1.104 + // connections. 1.105 + nsresult PruneDeadConnections(); 1.106 + 1.107 + // Close all idle persistent connections and prevent any active connections 1.108 + // from being reused. Optional connection info resets CI specific 1.109 + // information such as Happy Eyeballs history. 1.110 + nsresult DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *); 1.111 + 1.112 + // called to get a reference to the socket transport service. the socket 1.113 + // transport service is not available when the connection manager is down. 1.114 + nsresult GetSocketThreadTarget(nsIEventTarget **); 1.115 + 1.116 + // called to indicate a transaction for the connectionInfo is likely coming 1.117 + // soon. The connection manager may use this information to start a TCP 1.118 + // and/or SSL level handshake for that resource immediately so that it is 1.119 + // ready when the transaction is submitted. No obligation is taken on by the 1.120 + // connection manager, nor is the submitter obligated to actually submit a 1.121 + // real transaction for this connectionInfo. 1.122 + nsresult SpeculativeConnect(nsHttpConnectionInfo *, 1.123 + nsIInterfaceRequestor *, 1.124 + uint32_t caps = 0); 1.125 + 1.126 + // called when a connection is done processing a transaction. if the 1.127 + // connection can be reused then it will be added to the idle list, else 1.128 + // it will be closed. 1.129 + nsresult ReclaimConnection(nsHttpConnection *conn); 1.130 + 1.131 + // called by the main thread to execute the taketransport() logic on the 1.132 + // socket thread after a 101 response has been received and the socket 1.133 + // needs to be transferred to an expectant upgrade listener such as 1.134 + // websockets. 1.135 + nsresult CompleteUpgrade(nsAHttpConnection *aConn, 1.136 + nsIHttpUpgradeListener *aUpgradeListener); 1.137 + 1.138 + // called to update a parameter after the connection manager has already 1.139 + // been initialized. 1.140 + nsresult UpdateParam(nsParamName name, uint16_t value); 1.141 + 1.142 + // called from main thread to post a new request token bucket 1.143 + // to the socket thread 1.144 + nsresult UpdateRequestTokenBucket(EventTokenBucket *aBucket); 1.145 + 1.146 + // Pipielining Interfaces and Datatypes 1.147 + 1.148 + const static uint32_t kPipelineInfoTypeMask = 0xffff0000; 1.149 + const static uint32_t kPipelineInfoIDMask = ~kPipelineInfoTypeMask; 1.150 + 1.151 + const static uint32_t kPipelineInfoTypeRed = 0x00010000; 1.152 + const static uint32_t kPipelineInfoTypeBad = 0x00020000; 1.153 + const static uint32_t kPipelineInfoTypeNeutral = 0x00040000; 1.154 + const static uint32_t kPipelineInfoTypeGood = 0x00080000; 1.155 + 1.156 + enum PipelineFeedbackInfoType 1.157 + { 1.158 + // Used when an HTTP response less than 1.1 is received 1.159 + RedVersionTooLow = kPipelineInfoTypeRed | kPipelineInfoTypeBad | 0x0001, 1.160 + 1.161 + // Used when a HTTP Server response header that is on the banned from 1.162 + // pipelining list is received 1.163 + RedBannedServer = kPipelineInfoTypeRed | kPipelineInfoTypeBad | 0x0002, 1.164 + 1.165 + // Used when a response is terminated early, when it fails an 1.166 + // integrity check such as assoc-req or when a 304 contained a Last-Modified 1.167 + // differnet than the entry being validated. 1.168 + RedCorruptedContent = kPipelineInfoTypeRed | kPipelineInfoTypeBad | 0x0004, 1.169 + 1.170 + // Used when a pipeline is only partly satisfied - for instance if the 1.171 + // server closed the connection after responding to the first 1.172 + // request but left some requests unprocessed. 1.173 + RedCanceledPipeline = kPipelineInfoTypeRed | kPipelineInfoTypeBad | 0x0005, 1.174 + 1.175 + // Used when a connection that we expected to stay persistently open 1.176 + // was closed by the server. Not used when simply timed out. 1.177 + BadExplicitClose = kPipelineInfoTypeBad | 0x0003, 1.178 + 1.179 + // Used when there is a gap of around 400 - 1200ms in between data being 1.180 + // read from the server 1.181 + BadSlowReadMinor = kPipelineInfoTypeBad | 0x0006, 1.182 + 1.183 + // Used when there is a gap of > 1200ms in between data being 1.184 + // read from the server 1.185 + BadSlowReadMajor = kPipelineInfoTypeBad | 0x0007, 1.186 + 1.187 + // Used when a response is received that is not framed with either chunked 1.188 + // encoding or a complete content length. 1.189 + BadInsufficientFraming = kPipelineInfoTypeBad | 0x0008, 1.190 + 1.191 + // Used when a very large response is recevied in a potential pipelining 1.192 + // context. Large responses cause head of line blocking. 1.193 + BadUnexpectedLarge = kPipelineInfoTypeBad | 0x000B, 1.194 + 1.195 + // Used when a response is received that has headers that appear to support 1.196 + // pipelining. 1.197 + NeutralExpectedOK = kPipelineInfoTypeNeutral | 0x0009, 1.198 + 1.199 + // Used when a response is received successfully to a pipelined request. 1.200 + GoodCompletedOK = kPipelineInfoTypeGood | 0x000A 1.201 + }; 1.202 + 1.203 + // called to provide information relevant to the pipelining manager 1.204 + // may be called from any thread 1.205 + void PipelineFeedbackInfo(nsHttpConnectionInfo *, 1.206 + PipelineFeedbackInfoType info, 1.207 + nsHttpConnection *, 1.208 + uint32_t); 1.209 + 1.210 + void ReportFailedToProcess(nsIURI *uri); 1.211 + 1.212 + // Causes a large amount of connection diagnostic information to be 1.213 + // printed to the javascript console 1.214 + void PrintDiagnostics(); 1.215 + 1.216 + //------------------------------------------------------------------------- 1.217 + // NOTE: functions below may be called only on the socket thread. 1.218 + //------------------------------------------------------------------------- 1.219 + 1.220 + // called to force the transaction queue to be processed once more, giving 1.221 + // preference to the specified connection. 1.222 + nsresult ProcessPendingQ(nsHttpConnectionInfo *); 1.223 + bool ProcessPendingQForEntry(nsHttpConnectionInfo *); 1.224 + 1.225 + // Try and process all pending transactions 1.226 + nsresult ProcessPendingQ(); 1.227 + 1.228 + // This is used to force an idle connection to be closed and removed from 1.229 + // the idle connection list. It is called when the idle connection detects 1.230 + // that the network peer has closed the transport. 1.231 + nsresult CloseIdleConnection(nsHttpConnection *); 1.232 + 1.233 + // The connection manager needs to know when a normal HTTP connection has been 1.234 + // upgraded to SPDY because the dispatch and idle semantics are a little 1.235 + // bit different. 1.236 + void ReportSpdyConnection(nsHttpConnection *, bool usingSpdy); 1.237 + 1.238 + // A spdy server can supply cwnd information for the session that is used 1.239 + // in future sessions to speed up the opening portions of the connection. 1.240 + void ReportSpdyCWNDSetting(nsHttpConnectionInfo *host, uint32_t cwndValue); 1.241 + uint32_t GetSpdyCWNDSetting(nsHttpConnectionInfo *host); 1.242 + 1.243 + bool SupportsPipelining(nsHttpConnectionInfo *); 1.244 + 1.245 + bool GetConnectionData(nsTArray<HttpRetParams> *); 1.246 + 1.247 + void ResetIPFamilyPreference(nsHttpConnectionInfo *); 1.248 + 1.249 +private: 1.250 + virtual ~nsHttpConnectionMgr(); 1.251 + 1.252 + enum PipeliningState { 1.253 + // Host has proven itself pipeline capable through past experience and 1.254 + // large pipeline depths are allowed on multiple connections. 1.255 + PS_GREEN, 1.256 + 1.257 + // Not enough information is available yet with this host to be certain 1.258 + // of pipeline capability. Small pipelines on a single connection are 1.259 + // allowed in order to decide whether or not to proceed to green. 1.260 + PS_YELLOW, 1.261 + 1.262 + // One or more bad events has happened that indicate that pipelining 1.263 + // to this host (or a particular type of transaction with this host) 1.264 + // is a bad idea. Pipelining is not currently allowed, but time and 1.265 + // other positive experiences will eventually allow it to try again. 1.266 + PS_RED 1.267 + }; 1.268 + 1.269 + class nsHalfOpenSocket; 1.270 + 1.271 + // nsConnectionEntry 1.272 + // 1.273 + // mCT maps connection info hash key to nsConnectionEntry object, which 1.274 + // contains list of active and idle connections as well as the list of 1.275 + // pending transactions. 1.276 + // 1.277 + class nsConnectionEntry 1.278 + { 1.279 + public: 1.280 + nsConnectionEntry(nsHttpConnectionInfo *ci); 1.281 + ~nsConnectionEntry(); 1.282 + 1.283 + nsHttpConnectionInfo *mConnInfo; 1.284 + nsTArray<nsHttpTransaction*> mPendingQ; // pending transaction queue 1.285 + nsTArray<nsHttpConnection*> mActiveConns; // active connections 1.286 + nsTArray<nsHttpConnection*> mIdleConns; // idle persistent connections 1.287 + nsTArray<nsHalfOpenSocket*> mHalfOpens; // half open connections 1.288 + 1.289 + // calculate the number of half open sockets that have not had at least 1 1.290 + // connection complete 1.291 + uint32_t UnconnectedHalfOpens(); 1.292 + 1.293 + // Remove a particular half open socket from the mHalfOpens array 1.294 + void RemoveHalfOpen(nsHalfOpenSocket *); 1.295 + 1.296 + // Pipeline depths for various states 1.297 + const static uint32_t kPipelineUnlimited = 1024; // fully open - extended green 1.298 + const static uint32_t kPipelineOpen = 6; // 6 on each conn - normal green 1.299 + const static uint32_t kPipelineRestricted = 2; // 2 on just 1 conn in yellow 1.300 + 1.301 + nsHttpConnectionMgr::PipeliningState PipelineState(); 1.302 + void OnPipelineFeedbackInfo( 1.303 + nsHttpConnectionMgr::PipelineFeedbackInfoType info, 1.304 + nsHttpConnection *, uint32_t); 1.305 + bool SupportsPipelining(); 1.306 + uint32_t MaxPipelineDepth(nsAHttpTransaction::Classifier classification); 1.307 + void CreditPenalty(); 1.308 + 1.309 + nsHttpConnectionMgr::PipeliningState mPipelineState; 1.310 + 1.311 + void SetYellowConnection(nsHttpConnection *); 1.312 + void OnYellowComplete(); 1.313 + uint32_t mYellowGoodEvents; 1.314 + uint32_t mYellowBadEvents; 1.315 + nsHttpConnection *mYellowConnection; 1.316 + 1.317 + // initialGreenDepth is the max depth of a pipeline when you first 1.318 + // transition to green. Normally this is kPipelineOpen, but it can 1.319 + // be kPipelineUnlimited in aggressive mode. 1.320 + uint32_t mInitialGreenDepth; 1.321 + 1.322 + // greenDepth is the current max allowed depth of a pipeline when 1.323 + // in the green state. Normally this starts as kPipelineOpen and 1.324 + // grows to kPipelineUnlimited after a pipeline of depth 3 has been 1.325 + // successfully transacted. 1.326 + uint32_t mGreenDepth; 1.327 + 1.328 + // pipeliningPenalty is the current amount of penalty points this host 1.329 + // entry has earned for participating in events that are not conducive 1.330 + // to good pipelines - such as head of line blocking, canceled pipelines, 1.331 + // etc.. penalties are paid back either through elapsed time or simply 1.332 + // healthy transactions. Having penalty points means that this host is 1.333 + // not currently eligible for pipelines. 1.334 + int16_t mPipeliningPenalty; 1.335 + 1.336 + // some penalty points only apply to particular classifications of 1.337 + // transactions - this allows a server that perhaps has head of line 1.338 + // blocking problems on CGI queries to still serve JS pipelined. 1.339 + int16_t mPipeliningClassPenalty[nsAHttpTransaction::CLASS_MAX]; 1.340 + 1.341 + // for calculating penalty repair credits 1.342 + TimeStamp mLastCreditTime; 1.343 + 1.344 + // Spdy sometimes resolves the address in the socket manager in order 1.345 + // to re-coalesce sharded HTTP hosts. The dotted decimal address is 1.346 + // combined with the Anonymous flag from the connection information 1.347 + // to build the hash key for hosts in the same ip pool. 1.348 + // 1.349 + // When a set of hosts are coalesced together one of them is marked 1.350 + // mSpdyPreferred. The mapping is maintained in the connection mananger 1.351 + // mSpdyPreferred hash. 1.352 + // 1.353 + nsCString mCoalescingKey; 1.354 + 1.355 + // The value of a recevied SPDY settings type 5 previously received 1.356 + // for this connection entry and the time it was set. 1.357 + uint32_t mSpdyCWND; 1.358 + TimeStamp mSpdyCWNDTimeStamp; 1.359 + 1.360 + // To have the UsingSpdy flag means some host with the same connection 1.361 + // entry has done NPN=spdy/* at some point. It does not mean every 1.362 + // connection is currently using spdy. 1.363 + bool mUsingSpdy; 1.364 + 1.365 + // mTestedSpdy is set after NPN negotiation has occurred and we know 1.366 + // with confidence whether a host speaks spdy or not (which is reflected 1.367 + // in mUsingSpdy). Before mTestedSpdy is set, handshake parallelism is 1.368 + // minimized so that we can multiplex on a single spdy connection. 1.369 + bool mTestedSpdy; 1.370 + 1.371 + bool mSpdyPreferred; 1.372 + 1.373 + // Flags to remember our happy-eyeballs decision. 1.374 + // Reset only by Ctrl-F5 reload. 1.375 + // True when we've first connected an IPv4 server for this host, 1.376 + // initially false. 1.377 + bool mPreferIPv4 : 1; 1.378 + // True when we've first connected an IPv6 server for this host, 1.379 + // initially false. 1.380 + bool mPreferIPv6 : 1; 1.381 + 1.382 + // Set the IP family preference flags according the connected family 1.383 + void RecordIPFamilyPreference(uint16_t family); 1.384 + // Resets all flags to their default values 1.385 + void ResetIPFamilyPreference(); 1.386 + }; 1.387 + 1.388 + // nsConnectionHandle 1.389 + // 1.390 + // thin wrapper around a real connection, used to keep track of references 1.391 + // to the connection to determine when the connection may be reused. the 1.392 + // transaction (or pipeline) owns a reference to this handle. this extra 1.393 + // layer of indirection greatly simplifies consumer code, avoiding the 1.394 + // need for consumer code to know when to give the connection back to the 1.395 + // connection manager. 1.396 + // 1.397 + class nsConnectionHandle : public nsAHttpConnection 1.398 + { 1.399 + public: 1.400 + NS_DECL_THREADSAFE_ISUPPORTS 1.401 + NS_DECL_NSAHTTPCONNECTION(mConn) 1.402 + 1.403 + nsConnectionHandle(nsHttpConnection *conn) { NS_ADDREF(mConn = conn); } 1.404 + virtual ~nsConnectionHandle(); 1.405 + 1.406 + nsHttpConnection *mConn; 1.407 + }; 1.408 + 1.409 + // nsHalfOpenSocket is used to hold the state of an opening TCP socket 1.410 + // while we wait for it to establish and bind it to a connection 1.411 + 1.412 + class nsHalfOpenSocket MOZ_FINAL : public nsIOutputStreamCallback, 1.413 + public nsITransportEventSink, 1.414 + public nsIInterfaceRequestor, 1.415 + public nsITimerCallback 1.416 + { 1.417 + public: 1.418 + NS_DECL_THREADSAFE_ISUPPORTS 1.419 + NS_DECL_NSIOUTPUTSTREAMCALLBACK 1.420 + NS_DECL_NSITRANSPORTEVENTSINK 1.421 + NS_DECL_NSIINTERFACEREQUESTOR 1.422 + NS_DECL_NSITIMERCALLBACK 1.423 + 1.424 + nsHalfOpenSocket(nsConnectionEntry *ent, 1.425 + nsAHttpTransaction *trans, 1.426 + uint32_t caps); 1.427 + ~nsHalfOpenSocket(); 1.428 + 1.429 + nsresult SetupStreams(nsISocketTransport **, 1.430 + nsIAsyncInputStream **, 1.431 + nsIAsyncOutputStream **, 1.432 + bool isBackup); 1.433 + nsresult SetupPrimaryStreams(); 1.434 + nsresult SetupBackupStreams(); 1.435 + void SetupBackupTimer(); 1.436 + void CancelBackupTimer(); 1.437 + void Abandon(); 1.438 + double Duration(TimeStamp epoch); 1.439 + nsISocketTransport *SocketTransport() { return mSocketTransport; } 1.440 + nsISocketTransport *BackupTransport() { return mBackupTransport; } 1.441 + 1.442 + nsAHttpTransaction *Transaction() { return mTransaction; } 1.443 + 1.444 + bool IsSpeculative() { return mSpeculative; } 1.445 + void SetSpeculative(bool val) { mSpeculative = val; } 1.446 + 1.447 + bool HasConnected() { return mHasConnected; } 1.448 + 1.449 + void PrintDiagnostics(nsCString &log); 1.450 + private: 1.451 + nsConnectionEntry *mEnt; 1.452 + nsRefPtr<nsAHttpTransaction> mTransaction; 1.453 + nsCOMPtr<nsISocketTransport> mSocketTransport; 1.454 + nsCOMPtr<nsIAsyncOutputStream> mStreamOut; 1.455 + nsCOMPtr<nsIAsyncInputStream> mStreamIn; 1.456 + uint32_t mCaps; 1.457 + 1.458 + // mSpeculative is set if the socket was created from 1.459 + // SpeculativeConnect(). It is cleared when a transaction would normally 1.460 + // start a new connection from scratch but instead finds this one in 1.461 + // the half open list and claims it for its own use. (which due to 1.462 + // the vagaries of scheduling from the pending queue might not actually 1.463 + // match up - but it prevents a speculative connection from opening 1.464 + // more connections that are needed.) 1.465 + bool mSpeculative; 1.466 + 1.467 + TimeStamp mPrimarySynStarted; 1.468 + TimeStamp mBackupSynStarted; 1.469 + 1.470 + // for syn retry 1.471 + nsCOMPtr<nsITimer> mSynTimer; 1.472 + nsCOMPtr<nsISocketTransport> mBackupTransport; 1.473 + nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut; 1.474 + nsCOMPtr<nsIAsyncInputStream> mBackupStreamIn; 1.475 + 1.476 + bool mHasConnected; 1.477 + }; 1.478 + friend class nsHalfOpenSocket; 1.479 + 1.480 + //------------------------------------------------------------------------- 1.481 + // NOTE: these members may be accessed from any thread (use mReentrantMonitor) 1.482 + //------------------------------------------------------------------------- 1.483 + 1.484 + ReentrantMonitor mReentrantMonitor; 1.485 + nsCOMPtr<nsIEventTarget> mSocketThreadTarget; 1.486 + 1.487 + // connection limits 1.488 + uint16_t mMaxConns; 1.489 + uint16_t mMaxPersistConnsPerHost; 1.490 + uint16_t mMaxPersistConnsPerProxy; 1.491 + uint16_t mMaxRequestDelay; // in seconds 1.492 + uint16_t mMaxPipelinedRequests; 1.493 + uint16_t mMaxOptimisticPipelinedRequests; 1.494 + bool mIsShuttingDown; 1.495 + 1.496 + //------------------------------------------------------------------------- 1.497 + // NOTE: these members are only accessed on the socket transport thread 1.498 + //------------------------------------------------------------------------- 1.499 + 1.500 + static PLDHashOperator ProcessOneTransactionCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *); 1.501 + static PLDHashOperator ProcessAllTransactionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *); 1.502 + 1.503 + static PLDHashOperator PruneDeadConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *); 1.504 + static PLDHashOperator ShutdownPassCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *); 1.505 + static PLDHashOperator PurgeExcessIdleConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *); 1.506 + static PLDHashOperator PurgeExcessSpdyConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *); 1.507 + static PLDHashOperator ClosePersistentConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *); 1.508 + bool ProcessPendingQForEntry(nsConnectionEntry *, bool considerAll); 1.509 + bool IsUnderPressure(nsConnectionEntry *ent, 1.510 + nsHttpTransaction::Classifier classification); 1.511 + bool AtActiveConnectionLimit(nsConnectionEntry *, uint32_t caps); 1.512 + nsresult TryDispatchTransaction(nsConnectionEntry *ent, 1.513 + bool onlyReusedConnection, 1.514 + nsHttpTransaction *trans); 1.515 + nsresult DispatchTransaction(nsConnectionEntry *, 1.516 + nsHttpTransaction *, 1.517 + nsHttpConnection *); 1.518 + nsresult DispatchAbstractTransaction(nsConnectionEntry *, 1.519 + nsAHttpTransaction *, 1.520 + uint32_t, 1.521 + nsHttpConnection *, 1.522 + int32_t); 1.523 + nsresult BuildPipeline(nsConnectionEntry *, 1.524 + nsAHttpTransaction *, 1.525 + nsHttpPipeline **); 1.526 + bool HasPipelines(nsConnectionEntry *); 1.527 + bool RestrictConnections(nsConnectionEntry *, bool = false); 1.528 + nsresult ProcessNewTransaction(nsHttpTransaction *); 1.529 + nsresult EnsureSocketThreadTarget(); 1.530 + void ClosePersistentConnections(nsConnectionEntry *ent); 1.531 + void ReportProxyTelemetry(nsConnectionEntry *ent); 1.532 + nsresult CreateTransport(nsConnectionEntry *, nsAHttpTransaction *, 1.533 + uint32_t, bool); 1.534 + void AddActiveConn(nsHttpConnection *, nsConnectionEntry *); 1.535 + void DecrementActiveConnCount(nsHttpConnection *); 1.536 + void StartedConnect(); 1.537 + void RecvdConnect(); 1.538 + 1.539 + nsConnectionEntry *GetOrCreateConnectionEntry(nsHttpConnectionInfo *); 1.540 + 1.541 + nsresult MakeNewConnection(nsConnectionEntry *ent, 1.542 + nsHttpTransaction *trans); 1.543 + bool AddToBestPipeline(nsConnectionEntry *ent, 1.544 + nsHttpTransaction *trans, 1.545 + nsHttpTransaction::Classifier classification, 1.546 + uint16_t depthLimit); 1.547 + 1.548 + // Manage the preferred spdy connection entry for this address 1.549 + nsConnectionEntry *GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry); 1.550 + void RemoveSpdyPreferredEnt(nsACString &aDottedDecimal); 1.551 + nsHttpConnection *GetSpdyPreferredConn(nsConnectionEntry *ent); 1.552 + nsDataHashtable<nsCStringHashKey, nsConnectionEntry *> mSpdyPreferredHash; 1.553 + nsConnectionEntry *LookupConnectionEntry(nsHttpConnectionInfo *ci, 1.554 + nsHttpConnection *conn, 1.555 + nsHttpTransaction *trans); 1.556 + 1.557 + void ProcessSpdyPendingQ(nsConnectionEntry *ent); 1.558 + static PLDHashOperator ProcessSpdyPendingQCB( 1.559 + const nsACString &key, nsAutoPtr<nsConnectionEntry> &ent, 1.560 + void *closure); 1.561 + 1.562 + // message handlers have this signature 1.563 + typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(int32_t, void *); 1.564 + 1.565 + // nsConnEvent 1.566 + // 1.567 + // subclass of nsRunnable used to marshall events to the socket transport 1.568 + // thread. this class is used to implement PostEvent. 1.569 + // 1.570 + class nsConnEvent; 1.571 + friend class nsConnEvent; 1.572 + class nsConnEvent : public nsRunnable 1.573 + { 1.574 + public: 1.575 + nsConnEvent(nsHttpConnectionMgr *mgr, 1.576 + nsConnEventHandler handler, 1.577 + int32_t iparam, 1.578 + void *vparam) 1.579 + : mMgr(mgr) 1.580 + , mHandler(handler) 1.581 + , mIParam(iparam) 1.582 + , mVParam(vparam) 1.583 + { 1.584 + NS_ADDREF(mMgr); 1.585 + } 1.586 + 1.587 + NS_IMETHOD Run() 1.588 + { 1.589 + (mMgr->*mHandler)(mIParam, mVParam); 1.590 + return NS_OK; 1.591 + } 1.592 + 1.593 + private: 1.594 + virtual ~nsConnEvent() 1.595 + { 1.596 + NS_RELEASE(mMgr); 1.597 + } 1.598 + 1.599 + nsHttpConnectionMgr *mMgr; 1.600 + nsConnEventHandler mHandler; 1.601 + int32_t mIParam; 1.602 + void *mVParam; 1.603 + }; 1.604 + 1.605 + nsresult PostEvent(nsConnEventHandler handler, 1.606 + int32_t iparam = 0, 1.607 + void *vparam = nullptr); 1.608 + 1.609 + // message handlers 1.610 + void OnMsgShutdown (int32_t, void *); 1.611 + void OnMsgShutdownConfirm (int32_t, void *); 1.612 + void OnMsgNewTransaction (int32_t, void *); 1.613 + void OnMsgReschedTransaction (int32_t, void *); 1.614 + void OnMsgCancelTransaction (int32_t, void *); 1.615 + void OnMsgProcessPendingQ (int32_t, void *); 1.616 + void OnMsgPruneDeadConnections (int32_t, void *); 1.617 + void OnMsgSpeculativeConnect (int32_t, void *); 1.618 + void OnMsgReclaimConnection (int32_t, void *); 1.619 + void OnMsgCompleteUpgrade (int32_t, void *); 1.620 + void OnMsgUpdateParam (int32_t, void *); 1.621 + void OnMsgDoShiftReloadConnectionCleanup (int32_t, void *); 1.622 + void OnMsgProcessFeedback (int32_t, void *); 1.623 + void OnMsgProcessAllSpdyPendingQ (int32_t, void *); 1.624 + void OnMsgUpdateRequestTokenBucket (int32_t, void *); 1.625 + 1.626 + // Total number of active connections in all of the ConnectionEntry objects 1.627 + // that are accessed from mCT connection table. 1.628 + uint16_t mNumActiveConns; 1.629 + // Total number of idle connections in all of the ConnectionEntry objects 1.630 + // that are accessed from mCT connection table. 1.631 + uint16_t mNumIdleConns; 1.632 + // Total number of spdy connections which are a subset of the active conns 1.633 + uint16_t mNumSpdyActiveConns; 1.634 + // Total number of connections in mHalfOpens ConnectionEntry objects 1.635 + // that are accessed from mCT connection table 1.636 + uint32_t mNumHalfOpenConns; 1.637 + 1.638 + // Holds time in seconds for next wake-up to prune dead connections. 1.639 + uint64_t mTimeOfNextWakeUp; 1.640 + // Timer for next pruning of dead connections. 1.641 + nsCOMPtr<nsITimer> mTimer; 1.642 + 1.643 + // A 1s tick to call nsHttpConnection::ReadTimeoutTick on 1.644 + // active http/1 connections and check for orphaned half opens. 1.645 + // Disabled when there are no active or half open connections. 1.646 + nsCOMPtr<nsITimer> mTimeoutTick; 1.647 + bool mTimeoutTickArmed; 1.648 + uint32_t mTimeoutTickNext; 1.649 + 1.650 + // 1.651 + // the connection table 1.652 + // 1.653 + // this table is indexed by connection key. each entry is a 1.654 + // nsConnectionEntry object. It is unlocked and therefore must only 1.655 + // be accessed from the socket thread. 1.656 + // 1.657 + nsClassHashtable<nsCStringHashKey, nsConnectionEntry> mCT; 1.658 + 1.659 + static PLDHashOperator ReadConnectionEntry(const nsACString &key, 1.660 + nsAutoPtr<nsConnectionEntry> &ent, 1.661 + void *aArg); 1.662 + 1.663 + // Read Timeout Tick handlers 1.664 + void ActivateTimeoutTick(); 1.665 + void TimeoutTick(); 1.666 + static PLDHashOperator TimeoutTickCB(const nsACString &key, 1.667 + nsAutoPtr<nsConnectionEntry> &ent, 1.668 + void *closure); 1.669 + 1.670 + // For diagnostics 1.671 + void OnMsgPrintDiagnostics(int32_t, void *); 1.672 + static PLDHashOperator PrintDiagnosticsCB(const nsACString &key, 1.673 + nsAutoPtr<nsConnectionEntry> &ent, 1.674 + void *closure); 1.675 + nsCString mLogData; 1.676 +}; 1.677 + 1.678 +}} // namespace mozilla::net 1.679 + 1.680 +#endif // !nsHttpConnectionMgr_h__