OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/core/quic_spdy_stream.h" | 5 #include "net/quic/core/quic_spdy_stream.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 } | 139 } |
140 | 140 |
141 bool QuicSpdyStream::IsDoneReading() const { | 141 bool QuicSpdyStream::IsDoneReading() const { |
142 bool done_reading_headers = FinishedReadingHeaders(); | 142 bool done_reading_headers = FinishedReadingHeaders(); |
143 bool done_reading_body = sequencer()->IsClosed(); | 143 bool done_reading_body = sequencer()->IsClosed(); |
144 bool done_reading_trailers = FinishedReadingTrailers(); | 144 bool done_reading_trailers = FinishedReadingTrailers(); |
145 return done_reading_headers && done_reading_body && done_reading_trailers; | 145 return done_reading_headers && done_reading_body && done_reading_trailers; |
146 } | 146 } |
147 | 147 |
148 bool QuicSpdyStream::HasBytesToRead() const { | 148 bool QuicSpdyStream::HasBytesToRead() const { |
149 bool headers_to_read = !decompressed_headers_.empty(); | 149 return sequencer()->HasBytesToRead(); |
150 bool body_to_read = sequencer()->HasBytesToRead(); | |
151 bool trailers_to_read = !decompressed_trailers_.empty(); | |
152 return headers_to_read || body_to_read || trailers_to_read; | |
153 } | |
154 | |
155 void QuicSpdyStream::MarkHeadersConsumed(size_t bytes_consumed) { | |
156 decompressed_headers_.erase(0, bytes_consumed); | |
157 if (FinishedReadingHeaders()) { | |
158 sequencer()->SetUnblocked(); | |
159 } | |
160 } | |
161 | |
162 void QuicSpdyStream::MarkTrailersConsumed(size_t bytes_consumed) { | |
163 decompressed_trailers_.erase(0, bytes_consumed); | |
164 } | 150 } |
165 | 151 |
166 void QuicSpdyStream::MarkTrailersConsumed() { | 152 void QuicSpdyStream::MarkTrailersConsumed() { |
167 trailers_consumed_ = true; | 153 trailers_consumed_ = true; |
168 } | 154 } |
169 | 155 |
170 void QuicSpdyStream::ConsumeHeaderList() { | 156 void QuicSpdyStream::ConsumeHeaderList() { |
171 header_list_.Clear(); | 157 header_list_.Clear(); |
172 if (FinishedReadingHeaders()) { | 158 if (FinishedReadingHeaders()) { |
173 sequencer()->SetUnblocked(); | 159 sequencer()->SetUnblocked(); |
174 } | 160 } |
175 } | 161 } |
176 | 162 |
177 void QuicSpdyStream::SetPriority(SpdyPriority priority) { | 163 void QuicSpdyStream::SetPriority(SpdyPriority priority) { |
178 DCHECK_EQ(0u, stream_bytes_written()); | 164 DCHECK_EQ(0u, stream_bytes_written()); |
179 spdy_session_->UpdateStreamPriority(id(), priority); | 165 spdy_session_->UpdateStreamPriority(id(), priority); |
180 priority_ = priority; | 166 priority_ = priority; |
181 } | 167 } |
182 | 168 |
183 void QuicSpdyStream::OnStreamHeaders(StringPiece headers_data) { | |
184 if (!headers_decompressed_) { | |
185 headers_data.AppendToString(&decompressed_headers_); | |
186 } else { | |
187 DCHECK(!trailers_decompressed_); | |
188 headers_data.AppendToString(&decompressed_trailers_); | |
189 } | |
190 } | |
191 | |
192 void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) { | 169 void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) { |
193 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective()); | 170 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective()); |
194 SetPriority(priority); | 171 SetPriority(priority); |
195 } | 172 } |
196 | 173 |
197 void QuicSpdyStream::OnStreamHeadersComplete(bool fin, size_t frame_len) { | |
198 if (!headers_decompressed_) { | |
199 OnInitialHeadersComplete(fin, frame_len); | |
200 } else { | |
201 OnTrailingHeadersComplete(fin, frame_len); | |
202 } | |
203 } | |
204 | |
205 void QuicSpdyStream::OnStreamHeaderList(bool fin, | 174 void QuicSpdyStream::OnStreamHeaderList(bool fin, |
206 size_t frame_len, | 175 size_t frame_len, |
207 const QuicHeaderList& header_list) { | 176 const QuicHeaderList& header_list) { |
208 // The headers list avoid infinite buffering by clearing the headers list | 177 // The headers list avoid infinite buffering by clearing the headers list |
209 // if the current headers are too large. So if the list is empty here | 178 // if the current headers are too large. So if the list is empty here |
210 // then the headers list must have been too large, and the stream should | 179 // then the headers list must have been too large, and the stream should |
211 // be reset. | 180 // be reset. |
| 181 // TODO(rch): Use an explicit "headers too large" signal. An empty header list |
| 182 // might be acceptable if it corresponds to a trailing header frame. |
212 if (FLAGS_quic_limit_uncompressed_headers && header_list.empty()) { | 183 if (FLAGS_quic_limit_uncompressed_headers && header_list.empty()) { |
213 OnHeadersTooLarge(); | 184 OnHeadersTooLarge(); |
214 if (IsDoneReading()) { | 185 if (IsDoneReading()) { |
215 return; | 186 return; |
216 } | 187 } |
217 } | 188 } |
218 if (!headers_decompressed_) { | 189 if (!headers_decompressed_) { |
219 OnInitialHeadersComplete(fin, frame_len, header_list); | 190 OnInitialHeadersComplete(fin, frame_len, header_list); |
220 } else { | 191 } else { |
221 OnTrailingHeadersComplete(fin, frame_len, header_list); | 192 OnTrailingHeadersComplete(fin, frame_len, header_list); |
222 } | 193 } |
223 } | 194 } |
224 | 195 |
225 void QuicSpdyStream::OnHeadersTooLarge() { | 196 void QuicSpdyStream::OnHeadersTooLarge() { |
226 Reset(QUIC_HEADERS_TOO_LARGE); | 197 Reset(QUIC_HEADERS_TOO_LARGE); |
227 } | 198 } |
228 | 199 |
229 void QuicSpdyStream::OnInitialHeadersComplete(bool fin, size_t /*frame_len*/) { | |
230 headers_decompressed_ = true; | |
231 if (fin) { | |
232 OnStreamFrame(QuicStreamFrame(id(), fin, 0, StringPiece())); | |
233 } | |
234 if (FinishedReadingHeaders()) { | |
235 sequencer()->SetUnblocked(); | |
236 } | |
237 } | |
238 | |
239 void QuicSpdyStream::OnInitialHeadersComplete( | 200 void QuicSpdyStream::OnInitialHeadersComplete( |
240 bool fin, | 201 bool fin, |
241 size_t /*frame_len*/, | 202 size_t /*frame_len*/, |
242 const QuicHeaderList& header_list) { | 203 const QuicHeaderList& header_list) { |
243 headers_decompressed_ = true; | 204 headers_decompressed_ = true; |
244 header_list_ = header_list; | 205 header_list_ = header_list; |
245 if (fin) { | 206 if (fin) { |
246 OnStreamFrame(QuicStreamFrame(id(), fin, 0, StringPiece())); | 207 OnStreamFrame(QuicStreamFrame(id(), fin, 0, StringPiece())); |
247 } | 208 } |
248 if (FinishedReadingHeaders()) { | 209 if (FinishedReadingHeaders()) { |
249 sequencer()->SetUnblocked(); | 210 sequencer()->SetUnblocked(); |
250 } | 211 } |
251 } | 212 } |
252 | 213 |
253 void QuicSpdyStream::OnPromiseHeaders(StringPiece headers_data) { | |
254 headers_data.AppendToString(&decompressed_headers_); | |
255 } | |
256 | |
257 void QuicSpdyStream::OnPromiseHeadersComplete( | |
258 QuicStreamId /* promised_stream_id */, | |
259 size_t /* frame_len */) { | |
260 // To be overridden in QuicSpdyClientStream. Not supported on | |
261 // server side. | |
262 session()->connection()->CloseConnection( | |
263 QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server", | |
264 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | |
265 return; | |
266 } | |
267 | |
268 void QuicSpdyStream::OnPromiseHeaderList( | 214 void QuicSpdyStream::OnPromiseHeaderList( |
269 QuicStreamId /* promised_id */, | 215 QuicStreamId /* promised_id */, |
270 size_t /* frame_len */, | 216 size_t /* frame_len */, |
271 const QuicHeaderList& /*header_list */) { | 217 const QuicHeaderList& /*header_list */) { |
272 // To be overridden in QuicSpdyClientStream. Not supported on | 218 // To be overridden in QuicSpdyClientStream. Not supported on |
273 // server side. | 219 // server side. |
274 session()->connection()->CloseConnection( | 220 session()->connection()->CloseConnection( |
275 QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server", | 221 QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server", |
276 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 222 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
277 return; | 223 return; |
278 } | 224 } |
279 | 225 |
280 void QuicSpdyStream::OnTrailingHeadersComplete(bool fin, size_t /*frame_len*/) { | |
281 DCHECK(!trailers_decompressed_); | |
282 if (fin_received()) { | |
283 DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id(); | |
284 session()->connection()->CloseConnection( | |
285 QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin", | |
286 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | |
287 return; | |
288 } | |
289 if (!fin) { | |
290 DLOG(ERROR) << "Trailers must have FIN set, on stream: " << id(); | |
291 session()->connection()->CloseConnection( | |
292 QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers", | |
293 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | |
294 return; | |
295 } | |
296 | |
297 size_t final_byte_offset = 0; | |
298 if (!SpdyUtils::ParseTrailers(decompressed_trailers().data(), | |
299 decompressed_trailers().length(), | |
300 &final_byte_offset, &received_trailers_)) { | |
301 DLOG(ERROR) << "Trailers are malformed: " << id(); | |
302 session()->connection()->CloseConnection( | |
303 QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed", | |
304 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | |
305 return; | |
306 } | |
307 | |
308 // The data on this stream ends at |final_byte_offset|. | |
309 DVLOG(1) << "Stream ends at byte offset: " << final_byte_offset | |
310 << " currently read: " << stream_bytes_read(); | |
311 trailers_decompressed_ = true; | |
312 OnStreamFrame(QuicStreamFrame(id(), fin, final_byte_offset, StringPiece())); | |
313 } | |
314 | |
315 void QuicSpdyStream::OnTrailingHeadersComplete( | 226 void QuicSpdyStream::OnTrailingHeadersComplete( |
316 bool fin, | 227 bool fin, |
317 size_t /*frame_len*/, | 228 size_t /*frame_len*/, |
318 const QuicHeaderList& header_list) { | 229 const QuicHeaderList& header_list) { |
319 DCHECK(!trailers_decompressed_); | 230 DCHECK(!trailers_decompressed_); |
320 if (fin_received()) { | 231 if (fin_received()) { |
321 DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id(); | 232 DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id(); |
322 session()->connection()->CloseConnection( | 233 session()->connection()->CloseConnection( |
323 QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin", | 234 QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin", |
324 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 235 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 void QuicSpdyStream::OnCanWrite() { | 283 void QuicSpdyStream::OnCanWrite() { |
373 ReliableQuicStream::OnCanWrite(); | 284 ReliableQuicStream::OnCanWrite(); |
374 | 285 |
375 // Trailers (and hence a FIN) may have been sent ahead of queued body bytes. | 286 // Trailers (and hence a FIN) may have been sent ahead of queued body bytes. |
376 if (!HasBufferedData() && fin_sent()) { | 287 if (!HasBufferedData() && fin_sent()) { |
377 CloseWriteSide(); | 288 CloseWriteSide(); |
378 } | 289 } |
379 } | 290 } |
380 | 291 |
381 bool QuicSpdyStream::FinishedReadingHeaders() const { | 292 bool QuicSpdyStream::FinishedReadingHeaders() const { |
382 return headers_decompressed_ && decompressed_headers_.empty() && | 293 return headers_decompressed_ && header_list_.empty(); |
383 header_list_.empty(); | |
384 } | 294 } |
385 | 295 |
386 bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header, | 296 bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header, |
387 int* status_code) const { | 297 int* status_code) const { |
388 SpdyHeaderBlock::const_iterator it = header.find(":status"); | 298 SpdyHeaderBlock::const_iterator it = header.find(":status"); |
389 if (it == header.end()) { | 299 if (it == header.end()) { |
390 return false; | 300 return false; |
391 } | 301 } |
392 const StringPiece status(it->second); | 302 const StringPiece status(it->second); |
393 if (status.size() != 3) { | 303 if (status.size() != 3) { |
(...skipping 11 matching lines...) Expand all Loading... |
405 } | 315 } |
406 | 316 |
407 bool QuicSpdyStream::FinishedReadingTrailers() const { | 317 bool QuicSpdyStream::FinishedReadingTrailers() const { |
408 // If no further trailing headers are expected, and the decompressed trailers | 318 // If no further trailing headers are expected, and the decompressed trailers |
409 // (if any) have been consumed, then reading of trailers is finished. | 319 // (if any) have been consumed, then reading of trailers is finished. |
410 if (!fin_received()) { | 320 if (!fin_received()) { |
411 return false; | 321 return false; |
412 } else if (!trailers_decompressed_) { | 322 } else if (!trailers_decompressed_) { |
413 return true; | 323 return true; |
414 } else { | 324 } else { |
415 return trailers_consumed_ && decompressed_trailers_.empty(); | 325 return trailers_consumed_; |
416 } | 326 } |
417 } | 327 } |
418 | 328 |
419 SpdyPriority QuicSpdyStream::priority() const { | 329 SpdyPriority QuicSpdyStream::priority() const { |
420 return priority_; | 330 return priority_; |
421 } | 331 } |
422 | 332 |
423 void QuicSpdyStream::ClearSession() { | 333 void QuicSpdyStream::ClearSession() { |
424 spdy_session_ = nullptr; | 334 spdy_session_ = nullptr; |
425 } | 335 } |
426 | 336 |
427 QuicConsumedData QuicSpdyStream::WritevDataInner( | 337 QuicConsumedData QuicSpdyStream::WritevDataInner( |
428 QuicIOVector iov, | 338 QuicIOVector iov, |
429 QuicStreamOffset offset, | 339 QuicStreamOffset offset, |
430 bool fin, | 340 bool fin, |
431 QuicAckListenerInterface* ack_notifier_delegate) { | 341 QuicAckListenerInterface* ack_notifier_delegate) { |
432 if (spdy_session_->headers_stream() != nullptr && | 342 if (spdy_session_->headers_stream() != nullptr && |
433 spdy_session_->force_hol_blocking()) { | 343 spdy_session_->force_hol_blocking()) { |
434 return spdy_session_->headers_stream()->WritevStreamData( | 344 return spdy_session_->headers_stream()->WritevStreamData( |
435 id(), iov, offset, fin, ack_notifier_delegate); | 345 id(), iov, offset, fin, ack_notifier_delegate); |
436 } | 346 } |
437 return ReliableQuicStream::WritevDataInner(iov, offset, fin, | 347 return ReliableQuicStream::WritevDataInner(iov, offset, fin, |
438 ack_notifier_delegate); | 348 ack_notifier_delegate); |
439 } | 349 } |
440 | 350 |
441 } // namespace net | 351 } // namespace net |
OLD | NEW |