Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: net/quic/core/quic_headers_stream.cc

Issue 2414193002: QUIC - bugfix for forced head of line blocking experiment. Guarded by ENABLED --FLAGS_quic_bugfix_f… (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/core/quic_headers_stream.h ('k') | net/quic/core/quic_headers_stream_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 380
381 // PUSH_PROMISE must not be the last frame sent out, at least followed by 381 // PUSH_PROMISE must not be the last frame sent out, at least followed by
382 // response headers. 382 // response headers.
383 push_promise.set_fin(false); 383 push_promise.set_fin(false);
384 384
385 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); 385 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
386 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); 386 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr);
387 return frame.size(); 387 return frame.size();
388 } 388 }
389 389
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
390 QuicConsumedData QuicHeadersStream::WritevStreamData( 409 QuicConsumedData QuicHeadersStream::WritevStreamData(
391 QuicStreamId id, 410 QuicStreamId id,
392 QuicIOVector iov, 411 QuicIOVector iov,
393 QuicStreamOffset offset, 412 QuicStreamOffset offset,
394 bool fin, 413 bool fin,
395 QuicAckListenerInterface* ack_notifier_delegate) { 414 QuicAckListenerInterface* ack_notifier_delegate) {
396 const size_t max_len = kSpdyInitialFrameSizeLimit - 415 const size_t max_len = kSpdyInitialFrameSizeLimit -
397 SpdyConstants::GetDataFrameMinimumSize(HTTP2); 416 SpdyConstants::GetDataFrameMinimumSize(HTTP2);
398 417
399 QuicConsumedData result(0, false); 418 QuicConsumedData result(0, false);
400 size_t total_length = iov.total_length; 419 size_t total_length = iov.total_length;
401 420
402 // Encapsulate the data into HTTP/2 DATA frames. The outer loop 421 if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) {
403 // handles each element of the source iov, the inner loop handles 422 // Encapsulate the data into HTTP/2 DATA frames. The outer loop
404 // the possibility of fragmenting eacho of those into multiple DATA 423 // handles each element of the source iov, the inner loop handles
405 // frames, as the DATA frames have a max size of 16KB. 424 // the possibility of fragmenting eacho of those into multiple DATA
406 for (int i = 0; i < iov.iov_count; i++) { 425 // frames, as the DATA frames have a max size of 16KB.
407 size_t offset = 0; 426 for (int i = 0; i < iov.iov_count; i++) {
408 const struct iovec* src_iov = &iov.iov[i]; 427 size_t offset = 0;
409 do { 428 const struct iovec* src_iov = &iov.iov[i];
410 size_t len = 429 do {
411 std::min(std::min(src_iov->iov_len - offset, max_len), total_length); 430 size_t len = std::min(std::min(src_iov->iov_len - offset, max_len),
412 char* data = static_cast<char*>(src_iov->iov_base) + offset; 431 total_length);
413 SpdyDataIR spdy_data(id, StringPiece(data, len)); 432 char* data = static_cast<char*>(src_iov->iov_base) + offset;
414 offset += len; 433 SpdyDataIR spdy_data(id, StringPiece(data, len));
415 // fin handling, set it only it only very last generated HTTP/2 434 offset += len;
416 // DATA frame. 435 // fin handling, only set it for the final HTTP/2 DATA frame.
417 bool last_iov = i == iov.iov_count - 1; 436 bool last_iov = i == iov.iov_count - 1;
418 bool last_fragment_within_iov = offset >= src_iov->iov_len; 437 bool last_fragment_within_iov = offset >= src_iov->iov_len;
419 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; 438 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
420 spdy_data.set_fin(frame_fin); 439 spdy_data.set_fin(frame_fin);
421 if (frame_fin) { 440 if (frame_fin) {
422 result.fin_consumed = true; 441 result.fin_consumed = true;
423 } 442 }
424 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); 443 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
425 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " 444 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len "
426 << len << " fin " << spdy_data.fin() << " remaining " 445 << len << " fin " << spdy_data.fin() << " remaining "
427 << src_iov->iov_len - offset; 446 << src_iov->iov_len - offset;
428 447
429 scoped_refptr<ForceHolAckListener> ack_listener; 448 scoped_refptr<ForceHolAckListener> ack_listener;
430 if (ack_notifier_delegate != nullptr) { 449 if (ack_notifier_delegate != nullptr) {
431 ack_listener = 450 ack_listener = new ForceHolAckListener(ack_notifier_delegate,
432 new ForceHolAckListener(ack_notifier_delegate, frame.size() - len); 451 frame.size() - len);
433 } 452 }
434 453
435 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, 454 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
436 ack_listener.get()); 455 ack_listener.get());
437 result.bytes_consumed += len; 456 result.bytes_consumed += len;
438 total_length -= len; 457 total_length -= len;
439 if (total_length <= 0) { 458 if (total_length <= 0) {
440 return result; 459 return result;
441 } 460 }
442 } while (offset < src_iov->iov_len); 461 } 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 }
443 } 505 }
506
444 return result; 507 return result;
445 } 508 }
446 509
447 void QuicHeadersStream::OnDataAvailable() { 510 void QuicHeadersStream::OnDataAvailable() {
448 char buffer[1024]; 511 char buffer[1024];
449 struct iovec iov; 512 struct iovec iov;
450 QuicTime timestamp(QuicTime::Zero()); 513 QuicTime timestamp(QuicTime::Zero());
451 while (true) { 514 while (true) {
452 iov.iov_base = buffer; 515 iov.iov_base = buffer;
453 iov.iov_len = arraysize(buffer); 516 iov.iov_len = arraysize(buffer);
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 return true; 706 return true;
644 } 707 }
645 frame_len_ -= len; 708 frame_len_ -= len;
646 // Ignore fin_ while there is more data coming, if frame_len_ > 0. 709 // Ignore fin_ while there is more data coming, if frame_len_ > 0.
647 spdy_session_->OnStreamFrameData(stream_id, data, len, 710 spdy_session_->OnStreamFrameData(stream_id, data, len,
648 frame_len_ > 0 ? false : fin_); 711 frame_len_ > 0 ? false : fin_);
649 return true; 712 return true;
650 } 713 }
651 714
652 } // namespace net 715 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/quic_headers_stream.h ('k') | net/quic/core/quic_headers_stream_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698