Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/http/nsHttpConnection.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 nsHttpConnection_h__
7
#define nsHttpConnection_h__
8
9
#include "nsHttpConnectionInfo.h"
10
#include "nsHttpResponseHead.h"
11
#include "nsAHttpTransaction.h"
12
#include "nsCOMPtr.h"
13
#include "nsAutoPtr.h"
14
#include "nsProxyRelease.h"
15
#include "prinrval.h"
16
#include "TunnelUtils.h"
17
#include "mozilla/Mutex.h"
18
#include "ARefBase.h"
19
#include "TimingStruct.h"
20
21
#include "nsIAsyncInputStream.h"
22
#include "nsIAsyncOutputStream.h"
23
#include "nsIInterfaceRequestor.h"
24
#include "nsITimer.h"
25
26
class nsISocketTransport;
27
class nsISSLSocketControl;
28
29
namespace mozilla {
30
namespace net {
31
32
class nsHttpHandler;
33
class ASpdySession;
34
35
// 1dcc863e-db90-4652-a1fe-13fea0b54e46
36
#define NS_HTTPCONNECTION_IID \
37
{ 0x1dcc863e, 0xdb90, 0x4652, {0xa1, 0xfe, 0x13, 0xfe, 0xa0, 0xb5, 0x4e, 0x46 }}
38
39
//-----------------------------------------------------------------------------
40
// nsHttpConnection - represents a connection to a HTTP server (or proxy)
41
//
42
// NOTE: this objects lives on the socket thread only.  it should not be
43
// accessed from any other thread.
44
//-----------------------------------------------------------------------------
45
46
class nsHttpConnection final : public nsAHttpSegmentReader
47
                             , public nsAHttpSegmentWriter
48
                             , public nsIInputStreamCallback
49
                             , public nsIOutputStreamCallback
50
                             , public nsITransportEventSink
51
                             , public nsIInterfaceRequestor
52
                             , public NudgeTunnelCallback
53
                             , public ARefBase
54
                             , public nsSupportsWeakReference
55
{
56
    virtual ~nsHttpConnection();
57
58
public:
59
    NS_DECLARE_STATIC_IID_ACCESSOR(NS_HTTPCONNECTION_IID)
60
    NS_DECL_THREADSAFE_ISUPPORTS
61
    NS_DECL_NSAHTTPSEGMENTREADER
62
    NS_DECL_NSAHTTPSEGMENTWRITER
63
    NS_DECL_NSIINPUTSTREAMCALLBACK
64
    NS_DECL_NSIOUTPUTSTREAMCALLBACK
65
    NS_DECL_NSITRANSPORTEVENTSINK
66
    NS_DECL_NSIINTERFACEREQUESTOR
67
    NS_DECL_NUDGETUNNELCALLBACK
68
69
    nsHttpConnection();
70
71
    // Initialize the connection:
72
    //  info        - specifies the connection parameters.
73
    //  maxHangTime - limits the amount of time this connection can spend on a
74
    //                single transaction before it should no longer be kept
75
    //                alive.  a value of 0xffff indicates no limit.
76
    MOZ_MUST_USE nsresult Init(nsHttpConnectionInfo *info, uint16_t maxHangTime,
77
                               nsISocketTransport *, nsIAsyncInputStream *,
78
                               nsIAsyncOutputStream *, bool connectedTransport,
79
                               nsIInterfaceRequestor *, PRIntervalTime);
80
81
    // Activate causes the given transaction to be processed on this
82
    // connection.  It fails if there is already an existing transaction unless
83
    // a multiplexing protocol such as SPDY is being used
84
    MOZ_MUST_USE nsresult Activate(nsAHttpTransaction *, uint32_t caps,
85
                                   int32_t pri);
86
87
    void SetFastOpen(bool aFastOpen);
88
    // Close this connection and return the transaction. The transaction is
89
    // restarted as well. This will only happened before connection is
90
    // connected.
91
    nsAHttpTransaction * CloseConnectionFastOpenTakesTooLongOrError(bool aCloseocketTransport);
92
93
    // Close the underlying socket transport.
94
    void Close(nsresult reason, bool aIsShutdown = false);
95
96
    //-------------------------------------------------------------------------
97
    // XXX document when these are ok to call
98
99
    bool IsKeepAlive()
100
0
    {
101
0
        return (mUsingSpdyVersion != SpdyVersion::NONE) || (mKeepAliveMask && mKeepAlive);
102
0
    }
103
    bool CanReuse();   // can this connection be reused?
104
    bool CanDirectlyActivate();
105
106
    // Returns time in seconds for how long connection can be reused.
107
    uint32_t TimeToLive();
108
109
    void DontReuse();
110
111
    bool IsProxyConnectInProgress()
112
0
    {
113
0
        return mProxyConnectInProgress;
114
0
    }
115
116
    bool LastTransactionExpectedNoContent()
117
0
    {
118
0
        return mLastTransactionExpectedNoContent;
119
0
    }
120
121
    void SetLastTransactionExpectedNoContent(bool val)
122
0
    {
123
0
        mLastTransactionExpectedNoContent = val;
124
0
    }
125
126
    bool NeedSpdyTunnel()
127
0
    {
128
0
        return mConnInfo->UsingHttpsProxy() && !mTLSFilter && mConnInfo->UsingConnect();
129
0
    }
130
131
    // A connection is forced into plaintext when it is intended to be used as a CONNECT
132
    // tunnel but the setup fails. The plaintext only carries the CONNECT error.
133
    void ForcePlainText()
134
0
    {
135
0
        mForcePlainText = true;
136
0
    }
137
138
0
    bool IsUrgentStartPreferred() const { return mUrgentStartPreferredKnown && mUrgentStartPreferred; }
139
    void SetUrgentStartPreferred(bool urgent);
140
141
0
    nsISocketTransport   *Transport()      { return mSocketTransport; }
142
0
    nsAHttpTransaction   *Transaction()    { return mTransaction; }
143
0
    nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; }
144
145
    // nsAHttpConnection compatible methods (non-virtual):
146
    MOZ_MUST_USE nsresult OnHeadersAvailable(nsAHttpTransaction *,
147
                                             nsHttpRequestHead *,
148
                                             nsHttpResponseHead *, bool *reset);
149
    void     CloseTransaction(nsAHttpTransaction *, nsresult reason,
150
                              bool aIsShutdown = false);
151
0
    void     GetConnectionInfo(nsHttpConnectionInfo **ci) { NS_IF_ADDREF(*ci = mConnInfo); }
152
    MOZ_MUST_USE nsresult TakeTransport(nsISocketTransport **,
153
                                        nsIAsyncInputStream **,
154
                                        nsIAsyncOutputStream **);
155
    void     GetSecurityInfo(nsISupports **);
156
0
    bool     IsPersistent() { return IsKeepAlive() && !mDontReuse; }
157
    bool     IsReused();
158
    void     SetIsReusedAfter(uint32_t afterMilliseconds);
159
    MOZ_MUST_USE nsresult PushBack(const char *data, uint32_t length);
160
    MOZ_MUST_USE nsresult ResumeSend();
161
    MOZ_MUST_USE nsresult ResumeRecv();
162
0
    int64_t  MaxBytesRead() {return mMaxBytesRead;}
163
0
    HttpVersion GetLastHttpResponseVersion() { return mLastHttpResponseVersion; }
164
165
    friend class HttpConnectionForceIO;
166
    MOZ_MUST_USE nsresult ForceSend();
167
    MOZ_MUST_USE nsresult ForceRecv();
168
169
    static MOZ_MUST_USE nsresult ReadFromStream(nsIInputStream *, void *,
170
                                                const char *, uint32_t,
171
                                                uint32_t, uint32_t *);
172
173
    // When a persistent connection is in the connection manager idle
174
    // connection pool, the nsHttpConnection still reads errors and hangups
175
    // on the socket so that it can be proactively released if the server
176
    // initiates a termination. Only call on socket thread.
177
    void BeginIdleMonitoring();
178
    void EndIdleMonitoring();
179
180
0
    bool UsingSpdy() { return (mUsingSpdyVersion != SpdyVersion::NONE); }
181
0
    SpdyVersion GetSpdyVersion() { return mUsingSpdyVersion; }
182
0
    bool EverUsedSpdy() { return mEverUsedSpdy; }
183
0
    PRIntervalTime Rtt() { return mRtt; }
184
185
    // true when connection SSL NPN phase is complete and we know
186
    // authoritatively whether UsingSpdy() or not.
187
0
    bool ReportedNPN() { return mReportedSpdy; }
188
189
    // When the connection is active this is called up to once every 1 second
190
    // return the interval (in seconds) that the connection next wants to
191
    // have this invoked. It might happen sooner depending on the needs of
192
    // other connections.
193
    uint32_t  ReadTimeoutTick(PRIntervalTime now);
194
195
    // For Active and Idle connections, this will be called when
196
    // mTCPKeepaliveTransitionTimer fires, to check if the TCP keepalive config
197
    // should move from short-lived (fast-detect) to long-lived.
198
    static void UpdateTCPKeepalive(nsITimer *aTimer, void *aClosure);
199
200
    // When the connection is active this is called every second
201
    void  ReadTimeoutTick();
202
203
0
    int64_t BytesWritten() { return mTotalBytesWritten; } // includes TLS
204
0
    int64_t ContentBytesWritten() { return mContentBytesWritten; }
205
206
    void    SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks);
207
    void    PrintDiagnostics(nsCString &log);
208
209
0
    void    SetTransactionCaps(uint32_t aCaps) { mTransactionCaps = aCaps; }
210
211
    // IsExperienced() returns true when the connection has started at least one
212
    // non null HTTP transaction of any version.
213
0
    bool    IsExperienced() { return mExperienced; }
214
215
    static MOZ_MUST_USE nsresult MakeConnectString(nsAHttpTransaction *trans,
216
                                                   nsHttpRequestHead *request,
217
                                                   nsACString &result);
218
    void    SetupSecondaryTLS();
219
    void    SetInSpdyTunnel(bool arg);
220
221
    // Check active connections for traffic (or not). SPDY connections send a
222
    // ping, ordinary HTTP connections get some time to get traffic to be
223
    // considered alive.
224
    void CheckForTraffic(bool check);
225
226
    // NoTraffic() returns true if there's been no traffic on the (non-spdy)
227
    // connection since CheckForTraffic() was called.
228
0
    bool NoTraffic() {
229
0
        return mTrafficStamp &&
230
0
            (mTrafficCount == (mTotalBytesWritten + mTotalBytesRead)) &&
231
0
            !mFastOpen;
232
0
    }
233
    // override of nsAHttpConnection
234
    virtual HttpVersion Version();
235
236
    bool TestJoinConnection(const nsACString &hostname, int32_t port);
237
    bool JoinConnection(const nsACString &hostname, int32_t port);
238
239
    void SetFastOpenStatus(uint8_t tfoStatus);
240
0
    uint8_t GetFastOpenStatus() {
241
0
      return mFastOpenStatus;
242
0
    }
243
244
    void SetEvent(nsresult aStatus);
245
246
    // Return true when the socket this connection is using has not been
247
    // authenticated using a client certificate.  Before SSL negotiation
248
    // has finished this returns false.
249
    bool NoClientCertAuth() const;
250
251
private:
252
    // Value (set in mTCPKeepaliveConfig) indicates which set of prefs to use.
253
    enum TCPKeepaliveConfig {
254
      kTCPKeepaliveDisabled = 0,
255
      kTCPKeepaliveShortLivedConfig,
256
      kTCPKeepaliveLongLivedConfig
257
    };
258
259
    // called to cause the underlying socket to start speaking SSL
260
    MOZ_MUST_USE nsresult InitSSLParams(bool connectingToProxy,
261
                                        bool ProxyStartSSL);
262
    MOZ_MUST_USE nsresult SetupNPNList(nsISSLSocketControl *ssl, uint32_t caps);
263
264
    MOZ_MUST_USE nsresult OnTransactionDone(nsresult reason);
265
    MOZ_MUST_USE nsresult OnSocketWritable();
266
    MOZ_MUST_USE nsresult OnSocketReadable();
267
268
    MOZ_MUST_USE nsresult SetupProxyConnect();
269
270
    PRIntervalTime IdleTime();
271
    bool     IsAlive();
272
273
    // Makes certain the SSL handshake is complete and NPN negotiation
274
    // has had a chance to happen
275
    MOZ_MUST_USE bool EnsureNPNComplete(nsresult &aOut0RTTWriteHandshakeValue,
276
                                        uint32_t &aOut0RTTBytesWritten);
277
    void     SetupSSL();
278
279
    // Start the Spdy transaction handler when NPN indicates spdy/*
280
    void     StartSpdy(nsISSLSocketControl *ssl, SpdyVersion versionLevel);
281
    // Like the above, but do the bare minimum to do 0RTT data, so we can back
282
    // it out, if necessary
283
    void     Start0RTTSpdy(SpdyVersion versionLevel);
284
285
    // Helpers for Start*Spdy
286
    nsresult TryTakeSubTransactions(nsTArray<RefPtr<nsAHttpTransaction> > &list);
287
    nsresult MoveTransactionsToSpdy(nsresult status, nsTArray<RefPtr<nsAHttpTransaction> > &list);
288
289
    // Directly Add a transaction to an active connection for SPDY
290
    MOZ_MUST_USE nsresult AddTransaction(nsAHttpTransaction *, int32_t);
291
292
    // Used to set TCP keepalives for fast detection of dead connections during
293
    // an initial period, and slower detection for long-lived connections.
294
    MOZ_MUST_USE nsresult StartShortLivedTCPKeepalives();
295
    MOZ_MUST_USE nsresult StartLongLivedTCPKeepalives();
296
    MOZ_MUST_USE nsresult DisableTCPKeepalives();
297
298
private:
299
    nsCOMPtr<nsISocketTransport>    mSocketTransport;
300
    nsCOMPtr<nsIAsyncInputStream>   mSocketIn;
301
    nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
302
303
    nsresult                        mSocketInCondition;
304
    nsresult                        mSocketOutCondition;
305
306
    nsCOMPtr<nsIInputStream>        mProxyConnectStream;
307
    nsCOMPtr<nsIInputStream>        mRequestStream;
308
309
    // mTransaction only points to the HTTP Transaction callbacks if the
310
    // transaction is open, otherwise it is null.
311
    RefPtr<nsAHttpTransaction>    mTransaction;
312
    RefPtr<TLSFilterTransaction>  mTLSFilter;
313
314
    RefPtr<nsHttpHandler>         mHttpHandler; // keep gHttpHandler alive
315
316
    Mutex                           mCallbacksLock;
317
    nsMainThreadPtrHandle<nsIInterfaceRequestor> mCallbacks;
318
319
    RefPtr<nsHttpConnectionInfo> mConnInfo;
320
321
    PRIntervalTime                  mLastReadTime;
322
    PRIntervalTime                  mLastWriteTime;
323
    PRIntervalTime                  mMaxHangTime;    // max download time before dropping keep-alive status
324
    PRIntervalTime                  mIdleTimeout;    // value of keep-alive: timeout=
325
    PRIntervalTime                  mConsiderReusedAfterInterval;
326
    PRIntervalTime                  mConsiderReusedAfterEpoch;
327
    int64_t                         mCurrentBytesRead;   // data read per activation
328
    int64_t                         mMaxBytesRead;       // max read in 1 activation
329
    int64_t                         mTotalBytesRead;     // total data read
330
    int64_t                         mTotalBytesWritten;  // does not include CONNECT tunnel
331
    int64_t                         mContentBytesWritten;  // does not include CONNECT tunnel or TLS
332
333
    RefPtr<nsIAsyncInputStream>   mInputOverflow;
334
335
    PRIntervalTime                  mRtt;
336
337
    // Whether the first non-null transaction dispatched on this connection was
338
    // urgent-start or not
339
    bool                            mUrgentStartPreferred;
340
    // A flag to prevent reset of mUrgentStartPreferred by subsequent transactions
341
    bool                            mUrgentStartPreferredKnown;
342
    bool                            mConnectedTransport;
343
    bool                            mKeepAlive;
344
    bool                            mKeepAliveMask;
345
    bool                            mDontReuse;
346
    bool                            mIsReused;
347
    bool                            mCompletedProxyConnect;
348
    bool                            mLastTransactionExpectedNoContent;
349
    bool                            mIdleMonitoring;
350
    bool                            mProxyConnectInProgress;
351
    bool                            mExperienced;
352
    bool                            mInSpdyTunnel;
353
    bool                            mForcePlainText;
354
355
    // A snapshot of current number of transfered bytes
356
    int64_t                         mTrafficCount;
357
    bool                            mTrafficStamp; // true then the above is set
358
359
    // The number of <= HTTP/1.1 transactions performed on this connection. This
360
    // excludes spdy transactions.
361
    uint32_t                        mHttp1xTransactionCount;
362
363
    // Keep-Alive: max="mRemainingConnectionUses" provides the number of future
364
    // transactions (including the current one) that the server expects to allow
365
    // on this persistent connection.
366
    uint32_t                        mRemainingConnectionUses;
367
368
    // SPDY related
369
    bool                            mNPNComplete;
370
    bool                            mSetupSSLCalled;
371
372
    // version level in use, 0 if unused
373
    SpdyVersion                     mUsingSpdyVersion;
374
375
    RefPtr<ASpdySession>            mSpdySession;
376
    int32_t                         mPriority;
377
    bool                            mReportedSpdy;
378
379
    // mUsingSpdyVersion is cleared when mSpdySession is freed, this is permanent
380
    bool                            mEverUsedSpdy;
381
382
    // mLastHttpResponseVersion stores the last response's http version seen.
383
    HttpVersion                     mLastHttpResponseVersion;
384
385
    // The capabailities associated with the most recent transaction
386
    uint32_t                        mTransactionCaps;
387
388
    // If a large keepalive has been requested for any trans,
389
    // scale the default by this factor
390
    uint32_t                        mDefaultTimeoutFactor;
391
392
    bool                            mResponseTimeoutEnabled;
393
394
    // Flag to indicate connection is in inital keepalive period (fast detect).
395
    uint32_t                        mTCPKeepaliveConfig;
396
    nsCOMPtr<nsITimer>              mTCPKeepaliveTransitionTimer;
397
398
private:
399
    // For ForceSend()
400
    static void                     ForceSendIO(nsITimer *aTimer, void *aClosure);
401
    MOZ_MUST_USE nsresult           MaybeForceSendIO();
402
    bool                            mForceSendPending;
403
    nsCOMPtr<nsITimer>              mForceSendTimer;
404
405
    // Helper variable for 0RTT handshake;
406
    bool                            m0RTTChecked; // Possible 0RTT has been
407
                                                  // checked.
408
    bool                            mWaitingFor0RTTResponse; // We have are
409
                                                             // sending 0RTT
410
                                                             // data and we
411
                                                             // are waiting
412
                                                             // for the end of
413
                                                             // the handsake.
414
    int64_t                        mContentBytesWritten0RTT;
415
    bool                           mEarlyDataNegotiated; //Only used for telemetry
416
    nsCString                      mEarlyNegotiatedALPN;
417
    bool                           mDid0RTTSpdy;
418
419
    bool                           mFastOpen;
420
    uint8_t                        mFastOpenStatus;
421
422
    bool                           mForceSendDuringFastOpenPending;
423
    bool                           mReceivedSocketWouldBlockDuringFastOpen;
424
    bool                           mCheckNetworkStallsWithTFO;
425
    PRIntervalTime                 mLastRequestBytesSentTime;
426
427
public:
428
    void BootstrapTimings(TimingStruct times);
429
private:
430
    TimingStruct    mBootstrappedTimings;
431
    bool            mBootstrappedTimingsSet;
432
};
433
434
NS_DEFINE_STATIC_IID_ACCESSOR(nsHttpConnection, NS_HTTPCONNECTION_IID)
435
436
} // namespace net
437
} // namespace mozilla
438
439
#endif // nsHttpConnection_h__