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