|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
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 mozilla_net_Http2Stream_h |
|
7 #define mozilla_net_Http2Stream_h |
|
8 |
|
9 #include "mozilla/Attributes.h" |
|
10 #include "nsAHttpTransaction.h" |
|
11 #include "nsISupportsPriority.h" |
|
12 |
|
13 namespace mozilla { |
|
14 namespace net { |
|
15 |
|
16 class Http2Session; |
|
17 class Http2Decompressor; |
|
18 |
|
19 class Http2Stream |
|
20 : public nsAHttpSegmentReader |
|
21 , public nsAHttpSegmentWriter |
|
22 { |
|
23 public: |
|
24 NS_DECL_NSAHTTPSEGMENTREADER |
|
25 NS_DECL_NSAHTTPSEGMENTWRITER |
|
26 |
|
27 enum stateType { |
|
28 IDLE, |
|
29 RESERVED_BY_REMOTE, |
|
30 OPEN, |
|
31 CLOSED_BY_LOCAL, |
|
32 CLOSED_BY_REMOTE, |
|
33 CLOSED |
|
34 }; |
|
35 |
|
36 const static int32_t kNormalPriority = 0x1000; |
|
37 const static int32_t kWorstPriority = kNormalPriority + nsISupportsPriority::PRIORITY_LOWEST; |
|
38 const static int32_t kBestPriority = kNormalPriority + nsISupportsPriority::PRIORITY_HIGHEST; |
|
39 |
|
40 Http2Stream(nsAHttpTransaction *, Http2Session *, int32_t); |
|
41 |
|
42 uint32_t StreamID() { return mStreamID; } |
|
43 Http2PushedStream *PushSource() { return mPushSource; } |
|
44 |
|
45 stateType HTTPState() { return mState; } |
|
46 void SetHTTPState(stateType val) { mState = val; } |
|
47 |
|
48 virtual nsresult ReadSegments(nsAHttpSegmentReader *, uint32_t, uint32_t *); |
|
49 virtual nsresult WriteSegments(nsAHttpSegmentWriter *, uint32_t, uint32_t *); |
|
50 virtual bool DeferCleanupOnSuccess() { return false; } |
|
51 |
|
52 const nsAFlatCString &Origin() const { return mOrigin; } |
|
53 |
|
54 bool RequestBlockedOnRead() |
|
55 { |
|
56 return static_cast<bool>(mRequestBlockedOnRead); |
|
57 } |
|
58 |
|
59 bool HasRegisteredID() { return mStreamID != 0; } |
|
60 |
|
61 nsAHttpTransaction *Transaction() { return mTransaction; } |
|
62 virtual nsILoadGroupConnectionInfo *LoadGroupConnectionInfo() |
|
63 { |
|
64 return mTransaction ? mTransaction->LoadGroupConnectionInfo() : nullptr; |
|
65 } |
|
66 |
|
67 void Close(nsresult reason); |
|
68 |
|
69 void SetRecvdFin(bool aStatus); |
|
70 bool RecvdFin() { return mRecvdFin; } |
|
71 |
|
72 void SetSentFin(bool aStatus); |
|
73 bool SentFin() { return mSentFin; } |
|
74 |
|
75 void SetRecvdReset(bool aStatus); |
|
76 bool RecvdReset() { return mRecvdReset; } |
|
77 |
|
78 void SetSentReset(bool aStatus); |
|
79 bool SentReset() { return mSentReset; } |
|
80 |
|
81 void SetCountAsActive(bool aStatus) { mCountAsActive = aStatus ? 1 : 0; } |
|
82 bool CountAsActive() { return mCountAsActive; } |
|
83 |
|
84 void SetAllHeadersReceived(bool aStatus) { mAllHeadersReceived = aStatus ? 1 : 0; } |
|
85 bool AllHeadersReceived() { return mAllHeadersReceived; } |
|
86 |
|
87 void UpdateTransportSendEvents(uint32_t count); |
|
88 void UpdateTransportReadEvents(uint32_t count); |
|
89 |
|
90 nsresult ConvertResponseHeaders(Http2Decompressor *, nsACString &, nsACString &); |
|
91 nsresult ConvertPushHeaders(Http2Decompressor *, nsACString &, nsACString &); |
|
92 |
|
93 bool AllowFlowControlledWrite(); |
|
94 void UpdateServerReceiveWindow(int32_t delta); |
|
95 int64_t ServerReceiveWindow() { return mServerReceiveWindow; } |
|
96 |
|
97 void DecrementClientReceiveWindow(uint32_t delta) { |
|
98 mClientReceiveWindow -= delta; |
|
99 mLocalUnacked += delta; |
|
100 } |
|
101 |
|
102 void IncrementClientReceiveWindow(uint32_t delta) { |
|
103 mClientReceiveWindow += delta; |
|
104 mLocalUnacked -= delta; |
|
105 } |
|
106 |
|
107 uint64_t LocalUnAcked() { return mLocalUnacked; } |
|
108 int64_t ClientReceiveWindow() { return mClientReceiveWindow; } |
|
109 |
|
110 bool BlockedOnRwin() { return mBlockedOnRwin; } |
|
111 |
|
112 uint32_t Priority() { return mPriority; } |
|
113 void SetPriority(uint32_t); |
|
114 |
|
115 // A pull stream has an implicit sink, a pushed stream has a sink |
|
116 // once it is matched to a pull stream. |
|
117 virtual bool HasSink() { return true; } |
|
118 |
|
119 virtual ~Http2Stream(); |
|
120 |
|
121 protected: |
|
122 static void CreatePushHashKey(const nsCString &scheme, |
|
123 const nsCString &hostHeader, |
|
124 uint64_t serial, |
|
125 const nsCSubstring &pathInfo, |
|
126 nsCString &outOrigin, |
|
127 nsCString &outKey); |
|
128 |
|
129 // These internal states track request generation |
|
130 enum upstreamStateType { |
|
131 GENERATING_HEADERS, |
|
132 GENERATING_BODY, |
|
133 SENDING_BODY, |
|
134 SENDING_FIN_STREAM, |
|
135 UPSTREAM_COMPLETE |
|
136 }; |
|
137 |
|
138 uint32_t mStreamID; |
|
139 |
|
140 // The session that this stream is a subset of |
|
141 Http2Session *mSession; |
|
142 |
|
143 nsCString mOrigin; |
|
144 nsCString mHeaderHost; |
|
145 nsCString mHeaderScheme; |
|
146 nsCString mHeaderPath; |
|
147 |
|
148 // Each stream goes from generating_headers to upstream_complete, perhaps |
|
149 // looping on multiple instances of generating_body and |
|
150 // sending_body for each frame in the upload. |
|
151 enum upstreamStateType mUpstreamState; |
|
152 |
|
153 // The HTTP/2 state for the stream from section 5.1 |
|
154 enum stateType mState; |
|
155 |
|
156 // Flag is set when all http request headers have been read and ID is stable |
|
157 uint32_t mAllHeadersSent : 1; |
|
158 |
|
159 // Flag is set when all http request headers have been read and ID is stable |
|
160 uint32_t mAllHeadersReceived : 1; |
|
161 |
|
162 void ChangeState(enum upstreamStateType); |
|
163 |
|
164 private: |
|
165 friend class nsAutoPtr<Http2Stream>; |
|
166 |
|
167 nsresult ParseHttpRequestHeaders(const char *, uint32_t, uint32_t *); |
|
168 void AdjustPushedPriority(); |
|
169 void AdjustInitialWindow(); |
|
170 nsresult TransmitFrame(const char *, uint32_t *, bool forceCommitment); |
|
171 void GenerateDataFrameHeader(uint32_t, bool); |
|
172 |
|
173 // The underlying HTTP transaction. This pointer is used as the key |
|
174 // in the Http2Session mStreamTransactionHash so it is important to |
|
175 // keep a reference to it as long as this stream is a member of that hash. |
|
176 // (i.e. don't change it or release it after it is set in the ctor). |
|
177 nsRefPtr<nsAHttpTransaction> mTransaction; |
|
178 |
|
179 // The underlying socket transport object is needed to propogate some events |
|
180 nsISocketTransport *mSocketTransport; |
|
181 |
|
182 // These are temporary state variables to hold the argument to |
|
183 // Read/WriteSegments so it can be accessed by On(read/write)segment |
|
184 // further up the stack. |
|
185 nsAHttpSegmentReader *mSegmentReader; |
|
186 nsAHttpSegmentWriter *mSegmentWriter; |
|
187 |
|
188 // The quanta upstream data frames are chopped into |
|
189 uint32_t mChunkSize; |
|
190 |
|
191 // Flag is set when the HTTP processor has more data to send |
|
192 // but has blocked in doing so. |
|
193 uint32_t mRequestBlockedOnRead : 1; |
|
194 |
|
195 // Flag is set after the response frame bearing the fin bit has |
|
196 // been processed. (i.e. after the server has closed). |
|
197 uint32_t mRecvdFin : 1; |
|
198 |
|
199 // Flag is set after RST_STREAM has been received for this stream |
|
200 uint32_t mRecvdReset : 1; |
|
201 |
|
202 // Flag is set after RST_STREAM has been generated for this stream |
|
203 uint32_t mSentReset : 1; |
|
204 |
|
205 // Flag is set when stream is counted towards MAX_CONCURRENT streams in session |
|
206 uint32_t mCountAsActive : 1; |
|
207 |
|
208 // Flag is set when a FIN has been placed on a data or header frame |
|
209 // (i.e after the client has closed) |
|
210 uint32_t mSentFin : 1; |
|
211 |
|
212 // Flag is set after the WAITING_FOR Transport event has been generated |
|
213 uint32_t mSentWaitingFor : 1; |
|
214 |
|
215 // Flag is set after TCP send autotuning has been disabled |
|
216 uint32_t mSetTCPSocketBuffer : 1; |
|
217 |
|
218 // The InlineFrame and associated data is used for composing control |
|
219 // frames and data frame headers. |
|
220 nsAutoArrayPtr<uint8_t> mTxInlineFrame; |
|
221 uint32_t mTxInlineFrameSize; |
|
222 uint32_t mTxInlineFrameUsed; |
|
223 |
|
224 // mTxStreamFrameSize tracks the progress of |
|
225 // transmitting a request body data frame. The data frame itself |
|
226 // is never copied into the spdy layer. |
|
227 uint32_t mTxStreamFrameSize; |
|
228 |
|
229 // Buffer for request header compression. |
|
230 nsCString mFlatHttpRequestHeaders; |
|
231 |
|
232 // Track the content-length of a request body so that we can |
|
233 // place the fin flag on the last data packet instead of waiting |
|
234 // for a stream closed indication. Relying on stream close results |
|
235 // in an extra 0-length runt packet and seems to have some interop |
|
236 // problems with the google servers. |
|
237 int64_t mRequestBodyLenRemaining; |
|
238 |
|
239 // 0 is highest.. up to 2^31 - 1 as lowest |
|
240 uint32_t mPriority; |
|
241 |
|
242 // mClientReceiveWindow, mServerReceiveWindow, and mLocalUnacked are for flow control. |
|
243 // *window are signed because the race conditions in asynchronous SETTINGS |
|
244 // messages can force them temporarily negative. |
|
245 |
|
246 // mClientReceiveWindow is how much data the server will send without getting a |
|
247 // window update |
|
248 int64_t mClientReceiveWindow; |
|
249 |
|
250 // mServerReceiveWindow is how much data the client is allowed to send without |
|
251 // getting a window update |
|
252 int64_t mServerReceiveWindow; |
|
253 |
|
254 // LocalUnacked is the number of bytes received by the client but not |
|
255 // yet reflected in a window update. Sending that update will increment |
|
256 // ClientReceiveWindow |
|
257 uint64_t mLocalUnacked; |
|
258 |
|
259 // True when sending is suspended becuase the server receive window is |
|
260 // <= 0 |
|
261 bool mBlockedOnRwin; |
|
262 |
|
263 // For Progress Events |
|
264 uint64_t mTotalSent; |
|
265 uint64_t mTotalRead; |
|
266 |
|
267 // For Http2Push |
|
268 Http2PushedStream *mPushSource; |
|
269 }; |
|
270 |
|
271 } // namespace mozilla::net |
|
272 } // namespace mozilla |
|
273 |
|
274 #endif // mozilla_net_Http2Stream_h |