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