Coverage Report

Created: 2018-09-25 14:53

/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__