|
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 "nsAHttpTransaction.h" |
|
11 #include "nsCOMPtr.h" |
|
12 #include "nsAutoPtr.h" |
|
13 #include "nsProxyRelease.h" |
|
14 #include "prinrval.h" |
|
15 |
|
16 #include "nsIAsyncInputStream.h" |
|
17 #include "nsIAsyncOutputStream.h" |
|
18 #include "nsIInterfaceRequestor.h" |
|
19 #include "nsITimer.h" |
|
20 |
|
21 class nsISocketTransport; |
|
22 |
|
23 namespace mozilla { |
|
24 namespace net { |
|
25 |
|
26 class nsHttpHandler; |
|
27 class ASpdySession; |
|
28 |
|
29 //----------------------------------------------------------------------------- |
|
30 // nsHttpConnection - represents a connection to a HTTP server (or proxy) |
|
31 // |
|
32 // NOTE: this objects lives on the socket thread only. it should not be |
|
33 // accessed from any other thread. |
|
34 //----------------------------------------------------------------------------- |
|
35 |
|
36 class nsHttpConnection : public nsAHttpSegmentReader |
|
37 , public nsAHttpSegmentWriter |
|
38 , public nsIInputStreamCallback |
|
39 , public nsIOutputStreamCallback |
|
40 , public nsITransportEventSink |
|
41 , public nsIInterfaceRequestor |
|
42 { |
|
43 public: |
|
44 NS_DECL_THREADSAFE_ISUPPORTS |
|
45 NS_DECL_NSAHTTPSEGMENTREADER |
|
46 NS_DECL_NSAHTTPSEGMENTWRITER |
|
47 NS_DECL_NSIINPUTSTREAMCALLBACK |
|
48 NS_DECL_NSIOUTPUTSTREAMCALLBACK |
|
49 NS_DECL_NSITRANSPORTEVENTSINK |
|
50 NS_DECL_NSIINTERFACEREQUESTOR |
|
51 |
|
52 nsHttpConnection(); |
|
53 virtual ~nsHttpConnection(); |
|
54 |
|
55 // Initialize the connection: |
|
56 // info - specifies the connection parameters. |
|
57 // maxHangTime - limits the amount of time this connection can spend on a |
|
58 // single transaction before it should no longer be kept |
|
59 // alive. a value of 0xffff indicates no limit. |
|
60 nsresult Init(nsHttpConnectionInfo *info, uint16_t maxHangTime, |
|
61 nsISocketTransport *, nsIAsyncInputStream *, |
|
62 nsIAsyncOutputStream *, nsIInterfaceRequestor *, |
|
63 PRIntervalTime); |
|
64 |
|
65 // Activate causes the given transaction to be processed on this |
|
66 // connection. It fails if there is already an existing transaction unless |
|
67 // a multiplexing protocol such as SPDY is being used |
|
68 nsresult Activate(nsAHttpTransaction *, uint32_t caps, int32_t pri); |
|
69 |
|
70 // Close the underlying socket transport. |
|
71 void Close(nsresult reason); |
|
72 |
|
73 //------------------------------------------------------------------------- |
|
74 // XXX document when these are ok to call |
|
75 |
|
76 bool SupportsPipelining(); |
|
77 bool IsKeepAlive() { return mUsingSpdyVersion || |
|
78 (mKeepAliveMask && mKeepAlive); } |
|
79 bool CanReuse(); // can this connection be reused? |
|
80 bool CanDirectlyActivate(); |
|
81 |
|
82 // Returns time in seconds for how long connection can be reused. |
|
83 uint32_t TimeToLive(); |
|
84 |
|
85 void DontReuse(); |
|
86 |
|
87 bool IsProxyConnectInProgress() |
|
88 { |
|
89 return mProxyConnectInProgress; |
|
90 } |
|
91 |
|
92 bool LastTransactionExpectedNoContent() |
|
93 { |
|
94 return mLastTransactionExpectedNoContent; |
|
95 } |
|
96 |
|
97 void SetLastTransactionExpectedNoContent(bool val) |
|
98 { |
|
99 mLastTransactionExpectedNoContent = val; |
|
100 } |
|
101 |
|
102 nsISocketTransport *Transport() { return mSocketTransport; } |
|
103 nsAHttpTransaction *Transaction() { return mTransaction; } |
|
104 nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; } |
|
105 |
|
106 // nsAHttpConnection compatible methods (non-virtual): |
|
107 nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpRequestHead *, nsHttpResponseHead *, bool *reset); |
|
108 void CloseTransaction(nsAHttpTransaction *, nsresult reason); |
|
109 void GetConnectionInfo(nsHttpConnectionInfo **ci) { NS_IF_ADDREF(*ci = mConnInfo); } |
|
110 nsresult TakeTransport(nsISocketTransport **, |
|
111 nsIAsyncInputStream **, |
|
112 nsIAsyncOutputStream **); |
|
113 void GetSecurityInfo(nsISupports **); |
|
114 bool IsPersistent() { return IsKeepAlive(); } |
|
115 bool IsReused(); |
|
116 void SetIsReusedAfter(uint32_t afterMilliseconds); |
|
117 nsresult PushBack(const char *data, uint32_t length); |
|
118 nsresult ResumeSend(); |
|
119 nsresult ResumeRecv(); |
|
120 int64_t MaxBytesRead() {return mMaxBytesRead;} |
|
121 uint8_t GetLastHttpResponseVersion() { return mLastHttpResponseVersion; } |
|
122 |
|
123 friend class nsHttpConnectionForceRecv; |
|
124 nsresult ForceRecv(); |
|
125 |
|
126 static NS_METHOD ReadFromStream(nsIInputStream *, void *, const char *, |
|
127 uint32_t, uint32_t, uint32_t *); |
|
128 |
|
129 // When a persistent connection is in the connection manager idle |
|
130 // connection pool, the nsHttpConnection still reads errors and hangups |
|
131 // on the socket so that it can be proactively released if the server |
|
132 // initiates a termination. Only call on socket thread. |
|
133 void BeginIdleMonitoring(); |
|
134 void EndIdleMonitoring(); |
|
135 |
|
136 bool UsingSpdy() { return !!mUsingSpdyVersion; } |
|
137 uint8_t GetSpdyVersion() { return mUsingSpdyVersion; } |
|
138 bool EverUsedSpdy() { return mEverUsedSpdy; } |
|
139 PRIntervalTime Rtt() { return mRtt; } |
|
140 |
|
141 // true when connection SSL NPN phase is complete and we know |
|
142 // authoritatively whether UsingSpdy() or not. |
|
143 bool ReportedNPN() { return mReportedSpdy; } |
|
144 |
|
145 // When the connection is active this is called up to once every 1 second |
|
146 // return the interval (in seconds) that the connection next wants to |
|
147 // have this invoked. It might happen sooner depending on the needs of |
|
148 // other connections. |
|
149 uint32_t ReadTimeoutTick(PRIntervalTime now); |
|
150 |
|
151 // For Active and Idle connections, this will be called when |
|
152 // mTCPKeepaliveTransitionTimer fires, to check if the TCP keepalive config |
|
153 // should move from short-lived (fast-detect) to long-lived. |
|
154 static void UpdateTCPKeepalive(nsITimer *aTimer, void *aClosure); |
|
155 |
|
156 nsAHttpTransaction::Classifier Classification() { return mClassification; } |
|
157 void Classify(nsAHttpTransaction::Classifier newclass) |
|
158 { |
|
159 mClassification = newclass; |
|
160 } |
|
161 |
|
162 // When the connection is active this is called every second |
|
163 void ReadTimeoutTick(); |
|
164 |
|
165 int64_t BytesWritten() { return mTotalBytesWritten; } |
|
166 |
|
167 void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks); |
|
168 void PrintDiagnostics(nsCString &log); |
|
169 |
|
170 void SetTransactionCaps(uint32_t aCaps) { mTransactionCaps = aCaps; } |
|
171 |
|
172 // IsExperienced() returns true when the connection has started at least one |
|
173 // non null HTTP transaction of any version. |
|
174 bool IsExperienced() { return mExperienced; } |
|
175 |
|
176 private: |
|
177 // Value (set in mTCPKeepaliveConfig) indicates which set of prefs to use. |
|
178 enum TCPKeepaliveConfig { |
|
179 kTCPKeepaliveDisabled = 0, |
|
180 kTCPKeepaliveShortLivedConfig, |
|
181 kTCPKeepaliveLongLivedConfig |
|
182 }; |
|
183 |
|
184 // called to cause the underlying socket to start speaking SSL |
|
185 nsresult ProxyStartSSL(); |
|
186 |
|
187 nsresult OnTransactionDone(nsresult reason); |
|
188 nsresult OnSocketWritable(); |
|
189 nsresult OnSocketReadable(); |
|
190 |
|
191 nsresult SetupProxyConnect(); |
|
192 |
|
193 PRIntervalTime IdleTime(); |
|
194 bool IsAlive(); |
|
195 bool SupportsPipelining(nsHttpResponseHead *); |
|
196 |
|
197 // Makes certain the SSL handshake is complete and NPN negotiation |
|
198 // has had a chance to happen |
|
199 bool EnsureNPNComplete(); |
|
200 void SetupSSL(uint32_t caps); |
|
201 |
|
202 // Start the Spdy transaction handler when NPN indicates spdy/* |
|
203 void StartSpdy(uint8_t versionLevel); |
|
204 |
|
205 // Directly Add a transaction to an active connection for SPDY |
|
206 nsresult AddTransaction(nsAHttpTransaction *, int32_t); |
|
207 |
|
208 // Used to set TCP keepalives for fast detection of dead connections during |
|
209 // an initial period, and slower detection for long-lived connections. |
|
210 nsresult StartShortLivedTCPKeepalives(); |
|
211 nsresult StartLongLivedTCPKeepalives(); |
|
212 nsresult DisableTCPKeepalives(); |
|
213 |
|
214 private: |
|
215 nsCOMPtr<nsISocketTransport> mSocketTransport; |
|
216 nsCOMPtr<nsIAsyncInputStream> mSocketIn; |
|
217 nsCOMPtr<nsIAsyncOutputStream> mSocketOut; |
|
218 |
|
219 nsresult mSocketInCondition; |
|
220 nsresult mSocketOutCondition; |
|
221 |
|
222 nsCOMPtr<nsIInputStream> mProxyConnectStream; |
|
223 nsCOMPtr<nsIInputStream> mRequestStream; |
|
224 |
|
225 // mTransaction only points to the HTTP Transaction callbacks if the |
|
226 // transaction is open, otherwise it is null. |
|
227 nsRefPtr<nsAHttpTransaction> mTransaction; |
|
228 |
|
229 nsRefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive |
|
230 |
|
231 Mutex mCallbacksLock; |
|
232 nsMainThreadPtrHandle<nsIInterfaceRequestor> mCallbacks; |
|
233 |
|
234 nsRefPtr<nsHttpConnectionInfo> mConnInfo; |
|
235 |
|
236 PRIntervalTime mLastReadTime; |
|
237 PRIntervalTime mLastWriteTime; |
|
238 PRIntervalTime mMaxHangTime; // max download time before dropping keep-alive status |
|
239 PRIntervalTime mIdleTimeout; // value of keep-alive: timeout= |
|
240 PRIntervalTime mConsiderReusedAfterInterval; |
|
241 PRIntervalTime mConsiderReusedAfterEpoch; |
|
242 int64_t mCurrentBytesRead; // data read per activation |
|
243 int64_t mMaxBytesRead; // max read in 1 activation |
|
244 int64_t mTotalBytesRead; // total data read |
|
245 int64_t mTotalBytesWritten; // does not include CONNECT tunnel |
|
246 |
|
247 nsRefPtr<nsIAsyncInputStream> mInputOverflow; |
|
248 |
|
249 PRIntervalTime mRtt; |
|
250 |
|
251 bool mKeepAlive; |
|
252 bool mKeepAliveMask; |
|
253 bool mDontReuse; |
|
254 bool mSupportsPipelining; |
|
255 bool mIsReused; |
|
256 bool mCompletedProxyConnect; |
|
257 bool mLastTransactionExpectedNoContent; |
|
258 bool mIdleMonitoring; |
|
259 bool mProxyConnectInProgress; |
|
260 bool mExperienced; |
|
261 |
|
262 // The number of <= HTTP/1.1 transactions performed on this connection. This |
|
263 // excludes spdy transactions. |
|
264 uint32_t mHttp1xTransactionCount; |
|
265 |
|
266 // Keep-Alive: max="mRemainingConnectionUses" provides the number of future |
|
267 // transactions (including the current one) that the server expects to allow |
|
268 // on this persistent connection. |
|
269 uint32_t mRemainingConnectionUses; |
|
270 |
|
271 nsAHttpTransaction::Classifier mClassification; |
|
272 |
|
273 // SPDY related |
|
274 bool mNPNComplete; |
|
275 bool mSetupSSLCalled; |
|
276 |
|
277 // version level in use, 0 if unused |
|
278 uint8_t mUsingSpdyVersion; |
|
279 |
|
280 nsRefPtr<ASpdySession> mSpdySession; |
|
281 int32_t mPriority; |
|
282 bool mReportedSpdy; |
|
283 |
|
284 // mUsingSpdyVersion is cleared when mSpdySession is freed, this is permanent |
|
285 bool mEverUsedSpdy; |
|
286 |
|
287 // mLastHttpResponseVersion stores the last response's http version seen. |
|
288 uint8_t mLastHttpResponseVersion; |
|
289 |
|
290 // The capabailities associated with the most recent transaction |
|
291 uint32_t mTransactionCaps; |
|
292 |
|
293 bool mResponseTimeoutEnabled; |
|
294 |
|
295 // Flag to indicate connection is in inital keepalive period (fast detect). |
|
296 uint32_t mTCPKeepaliveConfig; |
|
297 nsCOMPtr<nsITimer> mTCPKeepaliveTransitionTimer; |
|
298 }; |
|
299 |
|
300 }} // namespace mozilla::net |
|
301 |
|
302 #endif // nsHttpConnection_h__ |