/src/mozilla-central/netwerk/protocol/http/nsHttpConnectionMgr.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* vim:set ts=4 sw=4 sts=4 et cin: */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #ifndef nsHttpConnectionMgr_h__ |
7 | | #define nsHttpConnectionMgr_h__ |
8 | | |
9 | | #include "nsHttpConnection.h" |
10 | | #include "nsHttpTransaction.h" |
11 | | #include "nsTArray.h" |
12 | | #include "nsThreadUtils.h" |
13 | | #include "nsClassHashtable.h" |
14 | | #include "nsDataHashtable.h" |
15 | | #include "nsAutoPtr.h" |
16 | | #include "mozilla/ReentrantMonitor.h" |
17 | | #include "mozilla/TimeStamp.h" |
18 | | #include "mozilla/Attributes.h" |
19 | | #include "AlternateServices.h" |
20 | | #include "ARefBase.h" |
21 | | #include "nsWeakReference.h" |
22 | | #include "TCPFastOpen.h" |
23 | | |
24 | | #include "nsINamed.h" |
25 | | #include "nsIObserver.h" |
26 | | #include "nsITimer.h" |
27 | | |
28 | | class nsIHttpUpgradeListener; |
29 | | |
30 | | namespace mozilla { |
31 | | namespace net { |
32 | | class EventTokenBucket; |
33 | | class NullHttpTransaction; |
34 | | struct HttpRetParams; |
35 | | |
36 | | // 8d411b53-54bc-4a99-8b78-ff125eab1564 |
37 | | #define NS_HALFOPENSOCKET_IID \ |
38 | | { 0x8d411b53, 0x54bc, 0x4a99, {0x8b, 0x78, 0xff, 0x12, 0x5e, 0xab, 0x15, 0x64 }} |
39 | | |
40 | | //----------------------------------------------------------------------------- |
41 | | |
42 | | // message handlers have this signature |
43 | | class nsHttpConnectionMgr; |
44 | | typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(int32_t, ARefBase *); |
45 | | |
46 | | class nsHttpConnectionMgr final : public nsIObserver |
47 | | , public AltSvcCache |
48 | | { |
49 | | public: |
50 | | NS_DECL_THREADSAFE_ISUPPORTS |
51 | | NS_DECL_NSIOBSERVER |
52 | | |
53 | | // parameter names |
54 | | enum nsParamName { |
55 | | MAX_URGENT_START_Q, |
56 | | MAX_CONNECTIONS, |
57 | | MAX_PERSISTENT_CONNECTIONS_PER_HOST, |
58 | | MAX_PERSISTENT_CONNECTIONS_PER_PROXY, |
59 | | MAX_REQUEST_DELAY, |
60 | | THROTTLING_ENABLED, |
61 | | THROTTLING_SUSPEND_FOR, |
62 | | THROTTLING_RESUME_FOR, |
63 | | THROTTLING_READ_LIMIT, |
64 | | THROTTLING_READ_INTERVAL, |
65 | | THROTTLING_HOLD_TIME, |
66 | | THROTTLING_MAX_TIME |
67 | | }; |
68 | | |
69 | | //------------------------------------------------------------------------- |
70 | | // NOTE: functions below may only be called on the main thread. |
71 | | //------------------------------------------------------------------------- |
72 | | |
73 | | nsHttpConnectionMgr(); |
74 | | |
75 | | MOZ_MUST_USE nsresult Init(uint16_t maxUrgentExcessiveConns, |
76 | | uint16_t maxConnections, |
77 | | uint16_t maxPersistentConnectionsPerHost, |
78 | | uint16_t maxPersistentConnectionsPerProxy, |
79 | | uint16_t maxRequestDelay, |
80 | | bool throttleEnabled, |
81 | | uint32_t throttleVersion, |
82 | | uint32_t throttleSuspendFor, |
83 | | uint32_t throttleResumeFor, |
84 | | uint32_t throttleReadLimit, |
85 | | uint32_t throttleReadInterval, |
86 | | uint32_t throttleHoldTime, |
87 | | uint32_t throttleMaxTime); |
88 | | MOZ_MUST_USE nsresult Shutdown(); |
89 | | |
90 | | //------------------------------------------------------------------------- |
91 | | // NOTE: functions below may be called on any thread. |
92 | | //------------------------------------------------------------------------- |
93 | | |
94 | | // Schedules next pruning of dead connection to happen after |
95 | | // given time. |
96 | | void PruneDeadConnectionsAfter(uint32_t time); |
97 | | |
98 | | // this cancels all outstanding transactions but does not shut down the mgr |
99 | | void AbortAndCloseAllConnections(int32_t, ARefBase *); |
100 | | |
101 | | // Stops timer scheduled for next pruning of dead connections if |
102 | | // there are no more idle connections or active spdy ones |
103 | | void ConditionallyStopPruneDeadConnectionsTimer(); |
104 | | |
105 | | // Stops timer used for the read timeout tick if there are no currently |
106 | | // active connections. |
107 | | void ConditionallyStopTimeoutTick(); |
108 | | |
109 | | // adds a transaction to the list of managed transactions. |
110 | | MOZ_MUST_USE nsresult AddTransaction(nsHttpTransaction *, int32_t priority); |
111 | | |
112 | | // called to reschedule the given transaction. it must already have been |
113 | | // added to the connection manager via AddTransaction. |
114 | | MOZ_MUST_USE nsresult RescheduleTransaction(nsHttpTransaction *, |
115 | | int32_t priority); |
116 | | |
117 | | // TOOD |
118 | | void UpdateClassOfServiceOnTransaction(nsHttpTransaction *, |
119 | | uint32_t classOfService); |
120 | | |
121 | | // cancels a transaction w/ the given reason. |
122 | | MOZ_MUST_USE nsresult CancelTransaction(nsHttpTransaction *, |
123 | | nsresult reason); |
124 | | MOZ_MUST_USE nsresult CancelTransactions(nsHttpConnectionInfo *, |
125 | | nsresult reason); |
126 | | |
127 | | // called to force the connection manager to prune its list of idle |
128 | | // connections. |
129 | | MOZ_MUST_USE nsresult PruneDeadConnections(); |
130 | | |
131 | | // called to close active connections with no registered "traffic" |
132 | | MOZ_MUST_USE nsresult PruneNoTraffic(); |
133 | | |
134 | | // "VerifyTraffic" means marking connections now, and then check again in |
135 | | // N seconds to see if there's been any traffic and if not, kill |
136 | | // that connection. |
137 | | MOZ_MUST_USE nsresult VerifyTraffic(); |
138 | | |
139 | | // Close all idle persistent connections and prevent any active connections |
140 | | // from being reused. Optional connection info resets CI specific |
141 | | // information such as Happy Eyeballs history. |
142 | | MOZ_MUST_USE nsresult DoShiftReloadConnectionCleanup(nsHttpConnectionInfo *); |
143 | | |
144 | | // called to get a reference to the socket transport service. the socket |
145 | | // transport service is not available when the connection manager is down. |
146 | | MOZ_MUST_USE nsresult GetSocketThreadTarget(nsIEventTarget **); |
147 | | |
148 | | // called to indicate a transaction for the connectionInfo is likely coming |
149 | | // soon. The connection manager may use this information to start a TCP |
150 | | // and/or SSL level handshake for that resource immediately so that it is |
151 | | // ready when the transaction is submitted. No obligation is taken on by the |
152 | | // connection manager, nor is the submitter obligated to actually submit a |
153 | | // real transaction for this connectionInfo. |
154 | | MOZ_MUST_USE nsresult SpeculativeConnect(nsHttpConnectionInfo *, |
155 | | nsIInterfaceRequestor *, |
156 | | uint32_t caps = 0, |
157 | | NullHttpTransaction * = nullptr); |
158 | | |
159 | | // called when a connection is done processing a transaction. if the |
160 | | // connection can be reused then it will be added to the idle list, else |
161 | | // it will be closed. |
162 | | MOZ_MUST_USE nsresult ReclaimConnection(nsHttpConnection *conn); |
163 | | |
164 | | // called by the main thread to execute the taketransport() logic on the |
165 | | // socket thread after a 101 response has been received and the socket |
166 | | // needs to be transferred to an expectant upgrade listener such as |
167 | | // websockets. |
168 | | MOZ_MUST_USE nsresult |
169 | | CompleteUpgrade(nsAHttpConnection *aConn, |
170 | | nsIHttpUpgradeListener *aUpgradeListener); |
171 | | |
172 | | // called to update a parameter after the connection manager has already |
173 | | // been initialized. |
174 | | MOZ_MUST_USE nsresult UpdateParam(nsParamName name, uint16_t value); |
175 | | |
176 | | // called from main thread to post a new request token bucket |
177 | | // to the socket thread |
178 | | MOZ_MUST_USE nsresult UpdateRequestTokenBucket(EventTokenBucket *aBucket); |
179 | | |
180 | | // clears the connection history mCT |
181 | | MOZ_MUST_USE nsresult ClearConnectionHistory(); |
182 | | |
183 | | void ReportFailedToProcess(nsIURI *uri); |
184 | | |
185 | | // Causes a large amount of connection diagnostic information to be |
186 | | // printed to the javascript console |
187 | | void PrintDiagnostics(); |
188 | | |
189 | | //------------------------------------------------------------------------- |
190 | | // NOTE: functions below may be called only on the socket thread. |
191 | | //------------------------------------------------------------------------- |
192 | | |
193 | | // called to change the connection entry associated with conn from specific into |
194 | | // a wildcard (i.e. http2 proxy friendy) mapping |
195 | | void MoveToWildCardConnEntry(nsHttpConnectionInfo *specificCI, |
196 | | nsHttpConnectionInfo *wildcardCI, |
197 | | nsHttpConnection *conn); |
198 | | |
199 | | // called to force the transaction queue to be processed once more, giving |
200 | | // preference to the specified connection. |
201 | | MOZ_MUST_USE nsresult ProcessPendingQ(nsHttpConnectionInfo *); |
202 | | MOZ_MUST_USE bool ProcessPendingQForEntry(nsHttpConnectionInfo *); |
203 | | |
204 | | // Try and process all pending transactions |
205 | | MOZ_MUST_USE nsresult ProcessPendingQ(); |
206 | | |
207 | | // This is used to force an idle connection to be closed and removed from |
208 | | // the idle connection list. It is called when the idle connection detects |
209 | | // that the network peer has closed the transport. |
210 | | MOZ_MUST_USE nsresult CloseIdleConnection(nsHttpConnection *); |
211 | | MOZ_MUST_USE nsresult RemoveIdleConnection(nsHttpConnection *); |
212 | | |
213 | | // The connection manager needs to know when a normal HTTP connection has been |
214 | | // upgraded to SPDY because the dispatch and idle semantics are a little |
215 | | // bit different. |
216 | | void ReportSpdyConnection(nsHttpConnection *, bool usingSpdy); |
217 | | |
218 | | bool GetConnectionData(nsTArray<HttpRetParams> *); |
219 | | |
220 | | void ResetIPFamilyPreference(nsHttpConnectionInfo *); |
221 | | |
222 | 0 | uint16_t MaxRequestDelay() { return mMaxRequestDelay; } |
223 | | |
224 | | // public, so that the SPDY/http2 seesions can activate |
225 | | void ActivateTimeoutTick(); |
226 | | |
227 | | nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId); |
228 | | |
229 | | // tracks and untracks active transactions according their throttle status |
230 | | void AddActiveTransaction(nsHttpTransaction* aTrans); |
231 | | void RemoveActiveTransaction(nsHttpTransaction* aTrans, |
232 | | Maybe<bool> const& aOverride = Nothing()); |
233 | | void UpdateActiveTransaction(nsHttpTransaction* aTrans); |
234 | | |
235 | | // called by nsHttpTransaction::WriteSegments. decides whether the transaction |
236 | | // should limit reading its reponse data. There are various conditions this |
237 | | // methods evaluates. If called by an active-tab non-throttled transaction, |
238 | | // the throttling window time will be prolonged. |
239 | | bool ShouldThrottle(nsHttpTransaction* aTrans); |
240 | | |
241 | | // prolongs the throttling time window to now + the window preferred delay. |
242 | | // called when: |
243 | | // - any transaction is activated |
244 | | // - or when a currently unthrottled transaction for the active window receives data |
245 | | void TouchThrottlingTimeWindow(bool aEnsureTicker = true); |
246 | | |
247 | | // return true iff the connection has pending transactions for the active tab. |
248 | | // it's mainly used to disallow throttling (limit reading) of a response |
249 | | // belonging to the same conn info to free up a connection ASAP. |
250 | | // NOTE: relatively expensive to call, there are two hashtable lookups. |
251 | | bool IsConnEntryUnderPressure(nsHttpConnectionInfo*); |
252 | | |
253 | | uint64_t CurrentTopLevelOuterContentWindowId() |
254 | 0 | { |
255 | 0 | return mCurrentTopLevelOuterContentWindowId; |
256 | 0 | } |
257 | | |
258 | | private: |
259 | | virtual ~nsHttpConnectionMgr(); |
260 | | |
261 | | class nsHalfOpenSocket; |
262 | | class PendingTransactionInfo; |
263 | | |
264 | | // nsConnectionEntry |
265 | | // |
266 | | // mCT maps connection info hash key to nsConnectionEntry object, which |
267 | | // contains list of active and idle connections as well as the list of |
268 | | // pending transactions. |
269 | | // |
270 | | class nsConnectionEntry |
271 | | { |
272 | | public: |
273 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsConnectionEntry) |
274 | | explicit nsConnectionEntry(nsHttpConnectionInfo *ci); |
275 | | |
276 | | RefPtr<nsHttpConnectionInfo> mConnInfo; |
277 | | nsTArray<RefPtr<PendingTransactionInfo> > mUrgentStartQ;// the urgent start transaction queue |
278 | | |
279 | | // This table provides a mapping from top level outer content window id |
280 | | // to a queue of pending transaction information. |
281 | | // The transaction's order in pending queue is decided by whether it's a |
282 | | // blocking transaction and its priority. |
283 | | // Note that the window id could be 0 if the http request |
284 | | // is initialized without a window. |
285 | | nsClassHashtable<nsUint64HashKey, |
286 | | nsTArray<RefPtr<PendingTransactionInfo>>> mPendingTransactionTable; |
287 | | nsTArray<RefPtr<nsHttpConnection> > mActiveConns; // active connections |
288 | | nsTArray<RefPtr<nsHttpConnection> > mIdleConns; // idle persistent connections |
289 | | nsTArray<nsHalfOpenSocket*> mHalfOpens; // half open connections |
290 | | nsTArray<RefPtr<nsHalfOpenSocket> > mHalfOpenFastOpenBackups; // backup half open connections for connection in fast open phase |
291 | | |
292 | | bool AvailableForDispatchNow(); |
293 | | |
294 | | // calculate the number of half open sockets that have not had at least 1 |
295 | | // connection complete |
296 | | uint32_t UnconnectedHalfOpens(); |
297 | | |
298 | | // Remove a particular half open socket from the mHalfOpens array |
299 | | void RemoveHalfOpen(nsHalfOpenSocket *); |
300 | | |
301 | | // Spdy sometimes resolves the address in the socket manager in order |
302 | | // to re-coalesce sharded HTTP hosts. The dotted decimal address is |
303 | | // combined with the Anonymous flag and OA from the connection information |
304 | | // to build the hash key for hosts in the same ip pool. |
305 | | // |
306 | | nsTArray<nsCString> mCoalescingKeys; |
307 | | |
308 | | // To have the UsingSpdy flag means some host with the same connection |
309 | | // entry has done NPN=spdy/* at some point. It does not mean every |
310 | | // connection is currently using spdy. |
311 | | bool mUsingSpdy : 1; |
312 | | |
313 | | // Flags to remember our happy-eyeballs decision. |
314 | | // Reset only by Ctrl-F5 reload. |
315 | | // True when we've first connected an IPv4 server for this host, |
316 | | // initially false. |
317 | | bool mPreferIPv4 : 1; |
318 | | // True when we've first connected an IPv6 server for this host, |
319 | | // initially false. |
320 | | bool mPreferIPv6 : 1; |
321 | | |
322 | | // True if this connection entry has initiated a socket |
323 | | bool mUsedForConnection : 1; |
324 | | |
325 | | // Try using TCP Fast Open. |
326 | | bool mUseFastOpen : 1; |
327 | | |
328 | | bool mDoNotDestroy : 1; |
329 | | |
330 | | // Set the IP family preference flags according the connected family |
331 | | void RecordIPFamilyPreference(uint16_t family); |
332 | | // Resets all flags to their default values |
333 | | void ResetIPFamilyPreference(); |
334 | | // True iff there is currently an established IP family preference |
335 | | bool PreferenceKnown() const; |
336 | | |
337 | | // Return the count of pending transactions for all window ids. |
338 | | size_t PendingQLength() const; |
339 | | |
340 | | // Add a transaction information into the pending queue in |
341 | | // |mPendingTransactionTable| according to the transaction's |
342 | | // top level outer content window id. |
343 | | void InsertTransaction(PendingTransactionInfo *info, |
344 | | bool aInsertAsFirstForTheSamePriority = false); |
345 | | |
346 | | // Append transactions to the |result| whose window id |
347 | | // is equal to |windowId|. |
348 | | // NOTE: maxCount == 0 will get all transactions in the queue. |
349 | | void AppendPendingQForFocusedWindow( |
350 | | uint64_t windowId, |
351 | | nsTArray<RefPtr<PendingTransactionInfo>> &result, |
352 | | uint32_t maxCount = 0); |
353 | | |
354 | | // Append transactions whose window id isn't equal to |windowId|. |
355 | | // NOTE: windowId == 0 will get all transactions for both |
356 | | // focused and non-focused windows. |
357 | | void AppendPendingQForNonFocusedWindows( |
358 | | uint64_t windowId, |
359 | | nsTArray<RefPtr<PendingTransactionInfo>> &result, |
360 | | uint32_t maxCount = 0); |
361 | | |
362 | | // Remove the empty pendingQ in |mPendingTransactionTable|. |
363 | | void RemoveEmptyPendingQ(); |
364 | | |
365 | | private: |
366 | | ~nsConnectionEntry(); |
367 | | }; |
368 | | |
369 | | public: |
370 | | static nsAHttpConnection *MakeConnectionHandle(nsHttpConnection *aWrapped); |
371 | | void RegisterOriginCoalescingKey(nsHttpConnection *, const nsACString &host, int32_t port); |
372 | | |
373 | | private: |
374 | | |
375 | | // nsHalfOpenSocket is used to hold the state of an opening TCP socket |
376 | | // while we wait for it to establish and bind it to a connection |
377 | | |
378 | | class nsHalfOpenSocket final : public nsIOutputStreamCallback, |
379 | | public nsITransportEventSink, |
380 | | public nsIInterfaceRequestor, |
381 | | public nsITimerCallback, |
382 | | public nsINamed, |
383 | | public nsSupportsWeakReference, |
384 | | public TCPFastOpen |
385 | | { |
386 | | ~nsHalfOpenSocket(); |
387 | | |
388 | | public: |
389 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_HALFOPENSOCKET_IID) |
390 | | NS_DECL_THREADSAFE_ISUPPORTS |
391 | | NS_DECL_NSIOUTPUTSTREAMCALLBACK |
392 | | NS_DECL_NSITRANSPORTEVENTSINK |
393 | | NS_DECL_NSIINTERFACEREQUESTOR |
394 | | NS_DECL_NSITIMERCALLBACK |
395 | | NS_DECL_NSINAMED |
396 | | |
397 | | nsHalfOpenSocket(nsConnectionEntry *ent, |
398 | | nsAHttpTransaction *trans, |
399 | | uint32_t caps, |
400 | | bool speculative, |
401 | | bool isFromPredictor, |
402 | | bool urgentStart); |
403 | | |
404 | | MOZ_MUST_USE nsresult SetupStreams(nsISocketTransport **, |
405 | | nsIAsyncInputStream **, |
406 | | nsIAsyncOutputStream **, |
407 | | bool isBackup); |
408 | | MOZ_MUST_USE nsresult SetupPrimaryStreams(); |
409 | | MOZ_MUST_USE nsresult SetupBackupStreams(); |
410 | | void SetupBackupTimer(); |
411 | | void CancelBackupTimer(); |
412 | | void Abandon(); |
413 | | double Duration(TimeStamp epoch); |
414 | 0 | nsISocketTransport *SocketTransport() { return mSocketTransport; } |
415 | 0 | nsISocketTransport *BackupTransport() { return mBackupTransport; } |
416 | | |
417 | 0 | nsAHttpTransaction *Transaction() { return mTransaction; } |
418 | | |
419 | 0 | bool IsSpeculative() { return mSpeculative; } |
420 | | |
421 | 0 | bool IsFromPredictor() { return mIsFromPredictor; } |
422 | | |
423 | 0 | bool Allow1918() { return mAllow1918; } |
424 | 0 | void SetAllow1918(bool val) { mAllow1918 = val; } |
425 | | |
426 | 0 | bool HasConnected() { return mHasConnected; } |
427 | | |
428 | | void PrintDiagnostics(nsCString &log); |
429 | | |
430 | | // Checks whether the transaction can be dispatched using this |
431 | | // half-open's connection. If this half-open is marked as urgent-start, |
432 | | // it only accepts urgent start transactions. Call only before Claim(). |
433 | | bool AcceptsTransaction(nsHttpTransaction* trans); |
434 | | bool Claim(); |
435 | | void Unclaim(); |
436 | | |
437 | | bool FastOpenEnabled() override; |
438 | | nsresult StartFastOpen() override; |
439 | | void SetFastOpenConnected(nsresult, bool aWillRetry) override; |
440 | | void FastOpenNotSupported() override; |
441 | | void SetFastOpenStatus(uint8_t tfoStatus) override; |
442 | | void CancelFastOpenConnection(); |
443 | | |
444 | | private: |
445 | | nsresult SetupConn(nsIAsyncOutputStream *out, |
446 | | bool aFastOpen); |
447 | | |
448 | | // To find out whether |mTransaction| is still in the connection entry's |
449 | | // pending queue. If the transaction is found and |removeWhenFound| is |
450 | | // true, the transaction will be removed from the pending queue. |
451 | | already_AddRefed<PendingTransactionInfo> |
452 | | FindTransactionHelper(bool removeWhenFound); |
453 | | |
454 | | RefPtr<nsAHttpTransaction> mTransaction; |
455 | | bool mDispatchedMTransaction; |
456 | | nsCOMPtr<nsISocketTransport> mSocketTransport; |
457 | | nsCOMPtr<nsIAsyncOutputStream> mStreamOut; |
458 | | nsCOMPtr<nsIAsyncInputStream> mStreamIn; |
459 | | uint32_t mCaps; |
460 | | |
461 | | // mSpeculative is set if the socket was created from |
462 | | // SpeculativeConnect(). It is cleared when a transaction would normally |
463 | | // start a new connection from scratch but instead finds this one in |
464 | | // the half open list and claims it for its own use. (which due to |
465 | | // the vagaries of scheduling from the pending queue might not actually |
466 | | // match up - but it prevents a speculative connection from opening |
467 | | // more connections that are needed.) |
468 | | bool mSpeculative; |
469 | | |
470 | | // If created with a non-null urgent transaction, remember it, so we can |
471 | | // mark the connection as urgent rightaway it's created. |
472 | | bool mUrgentStart; |
473 | | |
474 | | // mIsFromPredictor is set if the socket originated from the network |
475 | | // Predictor. It is used to gather telemetry data on used speculative |
476 | | // connections from the predictor. |
477 | | bool mIsFromPredictor; |
478 | | |
479 | | bool mAllow1918; |
480 | | |
481 | | TimeStamp mPrimarySynStarted; |
482 | | TimeStamp mBackupSynStarted; |
483 | | |
484 | | // mHasConnected tracks whether one of the sockets has completed the |
485 | | // connection process. It may have completed unsuccessfully. |
486 | | bool mHasConnected; |
487 | | |
488 | | bool mPrimaryConnectedOK; |
489 | | bool mBackupConnectedOK; |
490 | | bool mBackupConnStatsSet; |
491 | | |
492 | | // A nsHalfOpenSocket can be made for a concrete non-null transaction, |
493 | | // but the transaction can be dispatch to another connection. In that |
494 | | // case we can free this transaction to be claimed by other |
495 | | // transactions. |
496 | | bool mFreeToUse; |
497 | | nsresult mPrimaryStreamStatus; |
498 | | |
499 | | bool mFastOpenInProgress; |
500 | | RefPtr<nsHttpConnection> mConnectionNegotiatingFastOpen; |
501 | | uint8_t mFastOpenStatus; |
502 | | |
503 | | RefPtr<nsConnectionEntry> mEnt; |
504 | | nsCOMPtr<nsITimer> mSynTimer; |
505 | | nsCOMPtr<nsISocketTransport> mBackupTransport; |
506 | | nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut; |
507 | | nsCOMPtr<nsIAsyncInputStream> mBackupStreamIn; |
508 | | }; |
509 | | friend class nsHalfOpenSocket; |
510 | | |
511 | | class PendingTransactionInfo final : public ARefBase |
512 | | { |
513 | | public: |
514 | | explicit PendingTransactionInfo(nsHttpTransaction * trans) |
515 | | : mTransaction(trans) |
516 | 0 | {} |
517 | | |
518 | | NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PendingTransactionInfo, override) |
519 | | |
520 | | void PrintDiagnostics(nsCString &log); |
521 | | public: // meant to be public. |
522 | | RefPtr<nsHttpTransaction> mTransaction; |
523 | | nsWeakPtr mHalfOpen; |
524 | | nsWeakPtr mActiveConn; |
525 | | |
526 | | private: |
527 | 0 | virtual ~PendingTransactionInfo() = default; |
528 | | }; |
529 | | friend class PendingTransactionInfo; |
530 | | |
531 | | class PendingComparator |
532 | | { |
533 | | public: |
534 | | bool Equals(const PendingTransactionInfo *aPendingTrans, |
535 | 0 | const nsAHttpTransaction *aTrans) const { |
536 | 0 | return aPendingTrans->mTransaction.get() == aTrans; |
537 | 0 | } |
538 | | }; |
539 | | |
540 | | //------------------------------------------------------------------------- |
541 | | // NOTE: these members may be accessed from any thread (use mReentrantMonitor) |
542 | | //------------------------------------------------------------------------- |
543 | | |
544 | | ReentrantMonitor mReentrantMonitor; |
545 | | nsCOMPtr<nsIEventTarget> mSocketThreadTarget; |
546 | | |
547 | | // connection limits |
548 | | uint16_t mMaxUrgentExcessiveConns; |
549 | | uint16_t mMaxConns; |
550 | | uint16_t mMaxPersistConnsPerHost; |
551 | | uint16_t mMaxPersistConnsPerProxy; |
552 | | uint16_t mMaxRequestDelay; // in seconds |
553 | | bool mThrottleEnabled; |
554 | | uint32_t mThrottleVersion; |
555 | | uint32_t mThrottleSuspendFor; |
556 | | uint32_t mThrottleResumeFor; |
557 | | uint32_t mThrottleReadLimit; |
558 | | uint32_t mThrottleReadInterval; |
559 | | uint32_t mThrottleHoldTime; |
560 | | TimeDuration mThrottleMaxTime; |
561 | | Atomic<bool, mozilla::Relaxed> mIsShuttingDown; |
562 | | |
563 | | //------------------------------------------------------------------------- |
564 | | // NOTE: these members are only accessed on the socket transport thread |
565 | | //------------------------------------------------------------------------- |
566 | | |
567 | | MOZ_MUST_USE bool ProcessPendingQForEntry(nsConnectionEntry *, |
568 | | bool considerAll); |
569 | | bool DispatchPendingQ(nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ, |
570 | | nsConnectionEntry *ent, |
571 | | bool considerAll); |
572 | | |
573 | | // This function selects transactions from mPendingTransactionTable to dispatch |
574 | | // according to the following conditions: |
575 | | // 1. When ActiveTabPriority() is false, only get transactions from the queue |
576 | | // whose window id is 0. |
577 | | // 2. If |considerAll| is false, either get transactions from the focused window |
578 | | // queue or non-focused ones. |
579 | | // 3. If |considerAll| is true, fill the |pendingQ| with the transactions from |
580 | | // both focused window and non-focused window queues. |
581 | | void PreparePendingQForDispatching(nsConnectionEntry *ent, |
582 | | nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ, |
583 | | bool considerAll); |
584 | | |
585 | | // Return total active connection count, which is the sum of |
586 | | // active connections and unconnected half open connections. |
587 | | uint32_t TotalActiveConnections(nsConnectionEntry *ent) const; |
588 | | |
589 | | // Return |mMaxPersistConnsPerProxy| or |mMaxPersistConnsPerHost|, |
590 | | // depending whether the proxy is used. |
591 | | uint32_t MaxPersistConnections(nsConnectionEntry *ent) const; |
592 | | |
593 | | bool AtActiveConnectionLimit(nsConnectionEntry *, uint32_t caps); |
594 | | MOZ_MUST_USE nsresult TryDispatchTransaction(nsConnectionEntry *ent, |
595 | | bool onlyReusedConnection, |
596 | | PendingTransactionInfo *pendingTransInfo); |
597 | | MOZ_MUST_USE nsresult TryDispatchTransactionOnIdleConn(nsConnectionEntry *ent, |
598 | | PendingTransactionInfo *pendingTransInfo, |
599 | | bool respectUrgency, |
600 | | bool *allUrgent = nullptr); |
601 | | MOZ_MUST_USE nsresult DispatchTransaction(nsConnectionEntry *, |
602 | | nsHttpTransaction *, |
603 | | nsHttpConnection *); |
604 | | MOZ_MUST_USE nsresult DispatchAbstractTransaction(nsConnectionEntry *, |
605 | | nsAHttpTransaction *, |
606 | | uint32_t, |
607 | | nsHttpConnection *, |
608 | | int32_t); |
609 | | bool RestrictConnections(nsConnectionEntry *); |
610 | | MOZ_MUST_USE nsresult ProcessNewTransaction(nsHttpTransaction *); |
611 | | MOZ_MUST_USE nsresult EnsureSocketThreadTarget(); |
612 | | void ClosePersistentConnections(nsConnectionEntry *ent); |
613 | | void ReportProxyTelemetry(nsConnectionEntry *ent); |
614 | | MOZ_MUST_USE nsresult CreateTransport(nsConnectionEntry *, |
615 | | nsAHttpTransaction *, uint32_t, bool, |
616 | | bool, bool, bool, |
617 | | PendingTransactionInfo *pendingTransInfo); |
618 | | void AddActiveConn(nsHttpConnection *, nsConnectionEntry *); |
619 | | void DecrementActiveConnCount(nsHttpConnection *); |
620 | | void StartedConnect(); |
621 | | void RecvdConnect(); |
622 | | |
623 | | // This function will unclaim the claimed connection or set a halfOpen |
624 | | // socket to the speculative state if the transaction claiming them ends up |
625 | | // using another connection. |
626 | | void ReleaseClaimedSockets(nsConnectionEntry *ent, |
627 | | PendingTransactionInfo * pendingTransInfo); |
628 | | |
629 | | void InsertTransactionSorted(nsTArray<RefPtr<PendingTransactionInfo> > &pendingQ, |
630 | | PendingTransactionInfo *pendingTransInfo, |
631 | | bool aInsertAsFirstForTheSamePriority = false); |
632 | | |
633 | | nsConnectionEntry *GetOrCreateConnectionEntry(nsHttpConnectionInfo *, |
634 | | bool allowWildCard); |
635 | | |
636 | | MOZ_MUST_USE nsresult MakeNewConnection(nsConnectionEntry *ent, |
637 | | PendingTransactionInfo *pendingTransInfo); |
638 | | |
639 | | // Manage h2 connection coalescing |
640 | | // The hashtable contains arrays of weak pointers to nsHttpConnections |
641 | | nsClassHashtable<nsCStringHashKey, nsTArray<nsWeakPtr> > mCoalescingHash; |
642 | | |
643 | | nsHttpConnection *FindCoalescableConnection(nsConnectionEntry *ent, bool justKidding); |
644 | | nsHttpConnection *FindCoalescableConnectionByHashKey(nsConnectionEntry *ent, const nsCString &key, bool justKidding); |
645 | | void UpdateCoalescingForNewConn(nsHttpConnection *conn, nsConnectionEntry *ent); |
646 | | nsHttpConnection *GetSpdyActiveConn(nsConnectionEntry *ent); |
647 | | |
648 | | void ProcessSpdyPendingQ(nsConnectionEntry *ent); |
649 | | void DispatchSpdyPendingQ(nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ, |
650 | | nsConnectionEntry *ent, |
651 | | nsHttpConnection *conn); |
652 | | // used to marshall events to the socket transport thread. |
653 | | MOZ_MUST_USE nsresult PostEvent(nsConnEventHandler handler, |
654 | | int32_t iparam = 0, |
655 | | ARefBase *vparam = nullptr); |
656 | | |
657 | | // Used to close all transactions in the |pendingQ| with the given |reason|. |
658 | | // Note that the |pendingQ| will be also cleared. |
659 | | void CancelTransactionsHelper( |
660 | | nsTArray<RefPtr<PendingTransactionInfo>> &pendingQ, |
661 | | const nsHttpConnectionInfo *ci, |
662 | | const nsConnectionEntry *ent, |
663 | | nsresult reason); |
664 | | |
665 | | // message handlers |
666 | | void OnMsgShutdown (int32_t, ARefBase *); |
667 | | void OnMsgShutdownConfirm (int32_t, ARefBase *); |
668 | | void OnMsgNewTransaction (int32_t, ARefBase *); |
669 | | void OnMsgReschedTransaction (int32_t, ARefBase *); |
670 | | void OnMsgUpdateClassOfServiceOnTransaction (int32_t, ARefBase *); |
671 | | void OnMsgCancelTransaction (int32_t, ARefBase *); |
672 | | void OnMsgCancelTransactions (int32_t, ARefBase *); |
673 | | void OnMsgProcessPendingQ (int32_t, ARefBase *); |
674 | | void OnMsgPruneDeadConnections (int32_t, ARefBase *); |
675 | | void OnMsgSpeculativeConnect (int32_t, ARefBase *); |
676 | | void OnMsgReclaimConnection (int32_t, ARefBase *); |
677 | | void OnMsgCompleteUpgrade (int32_t, ARefBase *); |
678 | | void OnMsgUpdateParam (int32_t, ARefBase *); |
679 | | void OnMsgDoShiftReloadConnectionCleanup (int32_t, ARefBase *); |
680 | | void OnMsgProcessFeedback (int32_t, ARefBase *); |
681 | | void OnMsgProcessAllSpdyPendingQ (int32_t, ARefBase *); |
682 | | void OnMsgUpdateRequestTokenBucket (int32_t, ARefBase *); |
683 | | void OnMsgVerifyTraffic (int32_t, ARefBase *); |
684 | | void OnMsgPruneNoTraffic (int32_t, ARefBase *); |
685 | | void OnMsgUpdateCurrentTopLevelOuterContentWindowId (int32_t, ARefBase *); |
686 | | |
687 | | // Total number of active connections in all of the ConnectionEntry objects |
688 | | // that are accessed from mCT connection table. |
689 | | uint16_t mNumActiveConns; |
690 | | // Total number of idle connections in all of the ConnectionEntry objects |
691 | | // that are accessed from mCT connection table. |
692 | | uint16_t mNumIdleConns; |
693 | | // Total number of spdy connections which are a subset of the active conns |
694 | | uint16_t mNumSpdyActiveConns; |
695 | | // Total number of connections in mHalfOpens ConnectionEntry objects |
696 | | // that are accessed from mCT connection table |
697 | | uint32_t mNumHalfOpenConns; |
698 | | |
699 | | // Holds time in seconds for next wake-up to prune dead connections. |
700 | | uint64_t mTimeOfNextWakeUp; |
701 | | // Timer for next pruning of dead connections. |
702 | | nsCOMPtr<nsITimer> mTimer; |
703 | | // Timer for pruning stalled connections after changed network. |
704 | | nsCOMPtr<nsITimer> mTrafficTimer; |
705 | | bool mPruningNoTraffic; |
706 | | |
707 | | // A 1s tick to call nsHttpConnection::ReadTimeoutTick on |
708 | | // active http/1 connections and check for orphaned half opens. |
709 | | // Disabled when there are no active or half open connections. |
710 | | nsCOMPtr<nsITimer> mTimeoutTick; |
711 | | bool mTimeoutTickArmed; |
712 | | uint32_t mTimeoutTickNext; |
713 | | |
714 | | // |
715 | | // the connection table |
716 | | // |
717 | | // this table is indexed by connection key. each entry is a |
718 | | // nsConnectionEntry object. It is unlocked and therefore must only |
719 | | // be accessed from the socket thread. |
720 | | // |
721 | | nsRefPtrHashtable<nsCStringHashKey, nsConnectionEntry> mCT; |
722 | | |
723 | | // Read Timeout Tick handlers |
724 | | void TimeoutTick(); |
725 | | |
726 | | // For diagnostics |
727 | | void OnMsgPrintDiagnostics(int32_t, ARefBase *); |
728 | | |
729 | | nsCString mLogData; |
730 | | uint64_t mCurrentTopLevelOuterContentWindowId; |
731 | | |
732 | | // Called on a pref change |
733 | | void SetThrottlingEnabled(bool aEnable); |
734 | | |
735 | | // we only want to throttle for a limited amount of time after a new |
736 | | // active transaction is added so that we don't block downloads on comet, |
737 | | // socket and any kind of longstanding requests that don't need bandwidth. |
738 | | // these methods track this time. |
739 | | bool InThrottlingTimeWindow(); |
740 | | |
741 | | // Two hashtalbes keeping track of active transactions regarding window id and throttling. |
742 | | // Used by the throttling algorithm to obtain number of transactions for the active tab |
743 | | // and for inactive tabs according their throttle status. |
744 | | // mActiveTransactions[0] are all unthrottled transactions, mActiveTransactions[1] throttled. |
745 | | nsClassHashtable<nsUint64HashKey, nsTArray<RefPtr<nsHttpTransaction>>> mActiveTransactions[2]; |
746 | | |
747 | | // V1 specific |
748 | | // Whether we are inside the "stop reading" interval, altered by the throttle ticker |
749 | | bool mThrottlingInhibitsReading; |
750 | | |
751 | | TimeStamp mThrottlingWindowEndsAt; |
752 | | |
753 | | // ticker for the 'stop reading'/'resume reading' signal |
754 | | nsCOMPtr<nsITimer> mThrottleTicker; |
755 | | // Checks if the combination of active transactions requires the ticker. |
756 | | bool IsThrottleTickerNeeded(); |
757 | | // The method also unschedules the delayed resume of background tabs timer |
758 | | // if the ticker was about to be scheduled. |
759 | | void EnsureThrottleTickerIfNeeded(); |
760 | | // V1: |
761 | | // Drops also the mThrottlingInhibitsReading flag. Immediate or delayed resume |
762 | | // of currently throttled transactions is not affected by this method. |
763 | | // V2: |
764 | | // Immediate or delayed resume of currently throttled transactions is not |
765 | | // affected by this method. |
766 | | void DestroyThrottleTicker(); |
767 | | // V1: |
768 | | // Handler for the ticker: alters the mThrottlingInhibitsReading flag. |
769 | | // V2: |
770 | | // Handler for the ticker: calls ResumeReading() for all throttled transactions. |
771 | | void ThrottlerTick(); |
772 | | |
773 | | // mechanism to delay immediate resume of background tabs and chrome initiated |
774 | | // throttled transactions after the last transaction blocking their unthrottle |
775 | | // has been removed. Needs to be delayed because during a page load there is |
776 | | // a number of intervals when there is no transaction that would cause throttling. |
777 | | // Hence, throttling of long standing responses, like downloads, would be mostly |
778 | | // ineffective if resumed during every such interval. |
779 | | nsCOMPtr<nsITimer> mDelayedResumeReadTimer; |
780 | | // Schedule the resume |
781 | | void DelayedResumeBackgroundThrottledTransactions(); |
782 | | // Simply destroys the timer |
783 | | void CancelDelayedResumeBackgroundThrottledTransactions(); |
784 | | // Handler for the timer: resumes all background throttled transactions |
785 | | void ResumeBackgroundThrottledTransactions(); |
786 | | |
787 | | // Simple helpers, iterates the given hash/array and resume. |
788 | | // @param excludeActive: skip active tabid transactions. |
789 | | void ResumeReadOf(nsClassHashtable<nsUint64HashKey, nsTArray<RefPtr<nsHttpTransaction>>>&, |
790 | | bool excludeActive = false); |
791 | | void ResumeReadOf(nsTArray<RefPtr<nsHttpTransaction>>*); |
792 | | |
793 | | // Cached status of the active tab active transactions existence, |
794 | | // saves a lot of hashtable lookups |
795 | | bool mActiveTabTransactionsExist; |
796 | | bool mActiveTabUnthrottledTransactionsExist; |
797 | | |
798 | | void LogActiveTransactions(char); |
799 | | |
800 | | nsTArray<RefPtr<PendingTransactionInfo>>* |
801 | | GetTransactionPendingQHelper(nsConnectionEntry *ent, nsAHttpTransaction *trans); |
802 | | |
803 | | // When current active tab is changed, this function uses |
804 | | // |previousWindowId| to select background transactions and |
805 | | // mCurrentTopLevelOuterContentWindowId| to select foreground transactions. |
806 | | // Then, it notifies selected transactions' connection of the new active tab id. |
807 | | void NotifyConnectionOfWindowIdChange(uint64_t previousWindowId); |
808 | | }; |
809 | | |
810 | | NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnectionMgr::nsHalfOpenSocket, NS_HALFOPENSOCKET_IID) |
811 | | |
812 | | } // namespace net |
813 | | } // namespace mozilla |
814 | | |
815 | | #endif // !nsHttpConnectionMgr_h__ |