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_headers_stream.h" | 5 #include "net/quic/core/quic_headers_stream.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 } | 307 } |
308 | 308 |
309 void OnReceiveCompressedFrame(SpdyStreamId stream_id, | 309 void OnReceiveCompressedFrame(SpdyStreamId stream_id, |
310 SpdyFrameType type, | 310 SpdyFrameType type, |
311 size_t frame_len) override { | 311 size_t frame_len) override { |
312 if (stream_->IsConnected()) { | 312 if (stream_->IsConnected()) { |
313 stream_->OnCompressedFrameSize(frame_len); | 313 stream_->OnCompressedFrameSize(frame_len); |
314 } | 314 } |
315 } | 315 } |
316 | 316 |
| 317 void set_max_uncompressed_header_bytes( |
| 318 size_t set_max_uncompressed_header_bytes) { |
| 319 header_list_.set_max_uncompressed_header_bytes( |
| 320 set_max_uncompressed_header_bytes); |
| 321 } |
| 322 |
317 private: | 323 private: |
318 void CloseConnection(const string& details) { | 324 void CloseConnection(const string& details) { |
319 if (stream_->IsConnected()) { | 325 if (stream_->IsConnected()) { |
320 stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | 326 stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, |
321 details); | 327 details); |
322 } | 328 } |
323 } | 329 } |
324 | 330 |
325 private: | 331 private: |
326 QuicHeadersStream* stream_; | 332 QuicHeadersStream* stream_; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 386 |
381 // PUSH_PROMISE must not be the last frame sent out, at least followed by | 387 // PUSH_PROMISE must not be the last frame sent out, at least followed by |
382 // response headers. | 388 // response headers. |
383 push_promise.set_fin(false); | 389 push_promise.set_fin(false); |
384 | 390 |
385 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); | 391 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); |
386 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); | 392 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); |
387 return frame.size(); | 393 return frame.size(); |
388 } | 394 } |
389 | 395 |
390 void QuicHeadersStream::WriteDataFrame( | |
391 QuicStreamId id, | |
392 StringPiece data, | |
393 bool fin, | |
394 QuicAckListenerInterface* ack_notifier_delegate) { | |
395 SpdyDataIR spdy_data(id, data); | |
396 spdy_data.set_fin(fin); | |
397 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); | |
398 scoped_refptr<ForceHolAckListener> ack_listener; | |
399 if (ack_notifier_delegate != nullptr) { | |
400 ack_listener = new ForceHolAckListener(ack_notifier_delegate, | |
401 frame.size() - data.length()); | |
402 } | |
403 // Use buffered writes so that coherence of framing is preserved | |
404 // between streams. | |
405 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, | |
406 ack_listener.get()); | |
407 } | |
408 | |
409 QuicConsumedData QuicHeadersStream::WritevStreamData( | 396 QuicConsumedData QuicHeadersStream::WritevStreamData( |
410 QuicStreamId id, | 397 QuicStreamId id, |
411 QuicIOVector iov, | 398 QuicIOVector iov, |
412 QuicStreamOffset offset, | 399 QuicStreamOffset offset, |
413 bool fin, | 400 bool fin, |
414 QuicAckListenerInterface* ack_notifier_delegate) { | 401 QuicAckListenerInterface* ack_notifier_delegate) { |
415 const size_t max_len = kSpdyInitialFrameSizeLimit - | 402 const size_t max_len = kSpdyInitialFrameSizeLimit - |
416 SpdyConstants::GetDataFrameMinimumSize(HTTP2); | 403 SpdyConstants::GetDataFrameMinimumSize(HTTP2); |
417 | 404 |
418 QuicConsumedData result(0, false); | 405 QuicConsumedData result(0, false); |
419 size_t total_length = iov.total_length; | 406 size_t total_length = iov.total_length; |
420 | 407 |
421 if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) { | 408 // Encapsulate the data into HTTP/2 DATA frames. The outer loop |
422 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | 409 // handles each element of the source iov, the inner loop handles |
423 // handles each element of the source iov, the inner loop handles | 410 // the possibility of fragmenting eacho of those into multiple DATA |
424 // the possibility of fragmenting eacho of those into multiple DATA | 411 // frames, as the DATA frames have a max size of 16KB. |
425 // frames, as the DATA frames have a max size of 16KB. | 412 for (int i = 0; i < iov.iov_count; i++) { |
426 for (int i = 0; i < iov.iov_count; i++) { | 413 size_t offset = 0; |
427 size_t offset = 0; | 414 const struct iovec* src_iov = &iov.iov[i]; |
428 const struct iovec* src_iov = &iov.iov[i]; | 415 do { |
429 do { | 416 size_t len = |
430 size_t len = std::min(std::min(src_iov->iov_len - offset, max_len), | 417 std::min(std::min(src_iov->iov_len - offset, max_len), total_length); |
431 total_length); | 418 char* data = static_cast<char*>(src_iov->iov_base) + offset; |
432 char* data = static_cast<char*>(src_iov->iov_base) + offset; | 419 SpdyDataIR spdy_data(id, StringPiece(data, len)); |
433 SpdyDataIR spdy_data(id, StringPiece(data, len)); | 420 offset += len; |
434 offset += len; | 421 // fin handling, set it only it only very last generated HTTP/2 |
435 // fin handling, only set it for the final HTTP/2 DATA frame. | 422 // DATA frame. |
436 bool last_iov = i == iov.iov_count - 1; | 423 bool last_iov = i == iov.iov_count - 1; |
437 bool last_fragment_within_iov = offset >= src_iov->iov_len; | 424 bool last_fragment_within_iov = offset >= src_iov->iov_len; |
438 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | 425 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; |
439 spdy_data.set_fin(frame_fin); | 426 spdy_data.set_fin(frame_fin); |
440 if (frame_fin) { | 427 if (frame_fin) { |
441 result.fin_consumed = true; | 428 result.fin_consumed = true; |
442 } | 429 } |
443 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); | 430 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); |
444 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " | 431 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " |
445 << len << " fin " << spdy_data.fin() << " remaining " | 432 << len << " fin " << spdy_data.fin() << " remaining " |
446 << src_iov->iov_len - offset; | 433 << src_iov->iov_len - offset; |
447 | 434 |
448 scoped_refptr<ForceHolAckListener> ack_listener; | 435 scoped_refptr<ForceHolAckListener> ack_listener; |
449 if (ack_notifier_delegate != nullptr) { | 436 if (ack_notifier_delegate != nullptr) { |
450 ack_listener = new ForceHolAckListener(ack_notifier_delegate, | 437 ack_listener = |
451 frame.size() - len); | 438 new ForceHolAckListener(ack_notifier_delegate, frame.size() - len); |
452 } | 439 } |
453 | 440 |
454 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, | 441 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, |
455 ack_listener.get()); | 442 ack_listener.get()); |
456 result.bytes_consumed += len; | 443 result.bytes_consumed += len; |
457 total_length -= len; | 444 total_length -= len; |
458 if (total_length <= 0) { | 445 if (total_length <= 0) { |
459 return result; | 446 return result; |
460 } | 447 } |
461 } while (offset < src_iov->iov_len); | 448 } while (offset < src_iov->iov_len); |
462 } | |
463 } else { | |
464 if (total_length == 0 && fin) { | |
465 WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate); | |
466 result.fin_consumed = true; | |
467 return result; | |
468 } | |
469 | |
470 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | |
471 // handles each element of the source iov, the inner loop handles | |
472 // the possibility of fragmenting each of those into multiple DATA | |
473 // frames, as the DATA frames have a max size of 16KB. | |
474 for (int i = 0; i < iov.iov_count; i++) { | |
475 size_t src_iov_offset = 0; | |
476 const struct iovec* src_iov = &iov.iov[i]; | |
477 do { | |
478 if (queued_data_bytes() > 0) { | |
479 // Limit the amount of buffering to the minimum needed to | |
480 // preserve framing. | |
481 return result; | |
482 } | |
483 size_t len = std::min( | |
484 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); | |
485 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; | |
486 src_iov_offset += len; | |
487 offset += len; | |
488 // fin handling, only set it for the final HTTP/2 DATA frame. | |
489 bool last_iov = i == iov.iov_count - 1; | |
490 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; | |
491 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | |
492 WriteDataFrame(id, StringPiece(data, len), frame_fin, | |
493 ack_notifier_delegate); | |
494 result.bytes_consumed += len; | |
495 if (frame_fin) { | |
496 result.fin_consumed = true; | |
497 } | |
498 DCHECK_GE(total_length, len); | |
499 total_length -= len; | |
500 if (total_length <= 0) { | |
501 return result; | |
502 } | |
503 } while (src_iov_offset < src_iov->iov_len); | |
504 } | |
505 } | 449 } |
506 | |
507 return result; | 450 return result; |
508 } | 451 } |
509 | 452 |
510 void QuicHeadersStream::OnDataAvailable() { | 453 void QuicHeadersStream::OnDataAvailable() { |
511 char buffer[1024]; | 454 char buffer[1024]; |
512 struct iovec iov; | 455 struct iovec iov; |
513 QuicTime timestamp(QuicTime::Zero()); | 456 QuicTime timestamp(QuicTime::Zero()); |
514 while (true) { | 457 while (true) { |
515 iov.iov_base = buffer; | 458 iov.iov_base = buffer; |
516 iov.iov_len = arraysize(buffer); | 459 iov.iov_len = arraysize(buffer); |
517 if (!sequencer()->GetReadableRegion(&iov, ×tamp)) { | 460 if (!sequencer()->GetReadableRegion(&iov, ×tamp)) { |
518 // No more data to read. | 461 // No more data to read. |
519 break; | 462 break; |
520 } | 463 } |
521 DCHECK(timestamp.IsInitialized()); | 464 DCHECK(timestamp.IsInitialized()); |
522 cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_); | 465 cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_); |
523 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base), | 466 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base), |
524 iov.iov_len) != iov.iov_len) { | 467 iov.iov_len) != iov.iov_len) { |
525 // Error processing data. | 468 // Error processing data. |
526 return; | 469 return; |
527 } | 470 } |
528 sequencer()->MarkConsumed(iov.iov_len); | 471 sequencer()->MarkConsumed(iov.iov_len); |
529 } | 472 } |
530 } | 473 } |
531 | 474 |
| 475 void QuicHeadersStream::set_max_uncompressed_header_bytes( |
| 476 size_t set_max_uncompressed_header_bytes) { |
| 477 spdy_framer_visitor_->set_max_uncompressed_header_bytes( |
| 478 set_max_uncompressed_header_bytes); |
| 479 } |
| 480 |
532 void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id, | 481 void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id, |
533 bool has_priority, | 482 bool has_priority, |
534 SpdyPriority priority, | 483 SpdyPriority priority, |
535 bool fin) { | 484 bool fin) { |
536 if (has_priority) { | 485 if (has_priority) { |
537 if (session()->perspective() == Perspective::IS_CLIENT) { | 486 if (session()->perspective() == Perspective::IS_CLIENT) { |
538 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | 487 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, |
539 "Server must not send priorities."); | 488 "Server must not send priorities."); |
540 return; | 489 return; |
541 } | 490 } |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 return true; | 655 return true; |
707 } | 656 } |
708 frame_len_ -= len; | 657 frame_len_ -= len; |
709 // Ignore fin_ while there is more data coming, if frame_len_ > 0. | 658 // Ignore fin_ while there is more data coming, if frame_len_ > 0. |
710 spdy_session_->OnStreamFrameData(stream_id, data, len, | 659 spdy_session_->OnStreamFrameData(stream_id, data, len, |
711 frame_len_ > 0 ? false : fin_); | 660 frame_len_ > 0 ? false : fin_); |
712 return true; | 661 return true; |
713 } | 662 } |
714 | 663 |
715 } // namespace net | 664 } // namespace net |
OLD | NEW |