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

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

Issue 2535373002: QUIC - bugfix for forced head of line blocking experiment. Guarded by ENABLED --FLAGS_quic_bugfix_f… (Closed)
Patch Set: Created 4 years 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 <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 378
379 // PUSH_PROMISE must not be the last frame sent out, at least followed by 379 // PUSH_PROMISE must not be the last frame sent out, at least followed by
380 // response headers. 380 // response headers.
381 push_promise.set_fin(false); 381 push_promise.set_fin(false);
382 382
383 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); 383 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
384 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); 384 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr);
385 return frame.size(); 385 return frame.size();
386 } 386 }
387 387
388 void QuicHeadersStream::WriteDataFrame(
389 QuicStreamId id,
390 StringPiece data,
391 bool fin,
392 QuicAckListenerInterface* ack_notifier_delegate) {
393 SpdyDataIR spdy_data(id, data);
394 spdy_data.set_fin(fin);
395 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
396 scoped_refptr<ForceHolAckListener> ack_listener;
397 if (ack_notifier_delegate != nullptr) {
398 ack_listener = new ForceHolAckListener(ack_notifier_delegate,
399 frame.size() - data.length());
400 }
401 // Use buffered writes so that coherence of framing is preserved
402 // between streams.
403 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
404 ack_listener.get());
405 }
406
388 QuicConsumedData QuicHeadersStream::WritevStreamData( 407 QuicConsumedData QuicHeadersStream::WritevStreamData(
389 QuicStreamId id, 408 QuicStreamId id,
390 QuicIOVector iov, 409 QuicIOVector iov,
391 QuicStreamOffset offset, 410 QuicStreamOffset offset,
392 bool fin, 411 bool fin,
393 QuicAckListenerInterface* ack_notifier_delegate) { 412 QuicAckListenerInterface* ack_notifier_delegate) {
394 const size_t max_len = kSpdyInitialFrameSizeLimit - 413 const size_t max_len = kSpdyInitialFrameSizeLimit -
395 SpdyConstants::GetDataFrameMinimumSize(HTTP2); 414 SpdyConstants::GetDataFrameMinimumSize(HTTP2);
396 415
397 QuicConsumedData result(0, false); 416 QuicConsumedData result(0, false);
398 size_t total_length = iov.total_length; 417 size_t total_length = iov.total_length;
399 418
400 // Encapsulate the data into HTTP/2 DATA frames. The outer loop 419 if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) {
401 // handles each element of the source iov, the inner loop handles 420 // Encapsulate the data into HTTP/2 DATA frames. The outer loop
402 // the possibility of fragmenting eacho of those into multiple DATA 421 // handles each element of the source iov, the inner loop handles
403 // frames, as the DATA frames have a max size of 16KB. 422 // the possibility of fragmenting eacho of those into multiple DATA
404 for (int i = 0; i < iov.iov_count; i++) { 423 // frames, as the DATA frames have a max size of 16KB.
405 size_t offset = 0; 424 for (int i = 0; i < iov.iov_count; i++) {
406 const struct iovec* src_iov = &iov.iov[i]; 425 size_t offset = 0;
407 do { 426 const struct iovec* src_iov = &iov.iov[i];
408 size_t len = 427 do {
409 std::min(std::min(src_iov->iov_len - offset, max_len), total_length); 428 size_t len = std::min(std::min(src_iov->iov_len - offset, max_len),
410 char* data = static_cast<char*>(src_iov->iov_base) + offset; 429 total_length);
411 SpdyDataIR spdy_data(id, StringPiece(data, len)); 430 char* data = static_cast<char*>(src_iov->iov_base) + offset;
412 offset += len; 431 SpdyDataIR spdy_data(id, StringPiece(data, len));
413 // fin handling, set it only it only very last generated HTTP/2 432 offset += len;
414 // DATA frame. 433 // fin handling, only set it for the final HTTP/2 DATA frame.
415 bool last_iov = i == iov.iov_count - 1; 434 bool last_iov = i == iov.iov_count - 1;
416 bool last_fragment_within_iov = offset >= src_iov->iov_len; 435 bool last_fragment_within_iov = offset >= src_iov->iov_len;
417 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; 436 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
418 spdy_data.set_fin(frame_fin); 437 spdy_data.set_fin(frame_fin);
419 if (frame_fin) { 438 if (frame_fin) {
420 result.fin_consumed = true; 439 result.fin_consumed = true;
421 } 440 }
422 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); 441 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
423 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " 442 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len "
424 << len << " fin " << spdy_data.fin() << " remaining " 443 << len << " fin " << spdy_data.fin() << " remaining "
425 << src_iov->iov_len - offset; 444 << src_iov->iov_len - offset;
426 445
427 scoped_refptr<ForceHolAckListener> ack_listener; 446 scoped_refptr<ForceHolAckListener> ack_listener;
428 if (ack_notifier_delegate != nullptr) { 447 if (ack_notifier_delegate != nullptr) {
429 ack_listener = 448 ack_listener = new ForceHolAckListener(ack_notifier_delegate,
430 new ForceHolAckListener(ack_notifier_delegate, frame.size() - len); 449 frame.size() - len);
431 } 450 }
432 451
433 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, 452 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
434 ack_listener.get()); 453 ack_listener.get());
435 result.bytes_consumed += len; 454 result.bytes_consumed += len;
436 total_length -= len; 455 total_length -= len;
437 if (total_length <= 0) { 456 if (total_length <= 0) {
438 return result; 457 return result;
439 } 458 }
440 } while (offset < src_iov->iov_len); 459 } while (offset < src_iov->iov_len);
460 }
461 } else {
462 if (total_length == 0 && fin) {
463 WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate);
464 result.fin_consumed = true;
465 return result;
466 }
467
468 // Encapsulate the data into HTTP/2 DATA frames. The outer loop
469 // handles each element of the source iov, the inner loop handles
470 // the possibility of fragmenting each of those into multiple DATA
471 // frames, as the DATA frames have a max size of 16KB.
472 for (int i = 0; i < iov.iov_count; i++) {
473 size_t src_iov_offset = 0;
474 const struct iovec* src_iov = &iov.iov[i];
475 do {
476 if (queued_data_bytes() > 0) {
477 // Limit the amount of buffering to the minimum needed to
478 // preserve framing.
479 return result;
480 }
481 size_t len = std::min(
482 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length);
483 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset;
484 src_iov_offset += len;
485 offset += len;
486 // fin handling, only set it for the final HTTP/2 DATA frame.
487 bool last_iov = i == iov.iov_count - 1;
488 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len;
489 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
490 WriteDataFrame(id, StringPiece(data, len), frame_fin,
491 ack_notifier_delegate);
492 result.bytes_consumed += len;
493 if (frame_fin) {
494 result.fin_consumed = true;
495 }
496 DCHECK_GE(total_length, len);
497 total_length -= len;
498 if (total_length <= 0) {
499 return result;
500 }
501 } while (src_iov_offset < src_iov->iov_len);
502 }
441 } 503 }
504
442 return result; 505 return result;
443 } 506 }
444 507
445 void QuicHeadersStream::OnDataAvailable() { 508 void QuicHeadersStream::OnDataAvailable() {
446 char buffer[1024]; 509 char buffer[1024];
447 struct iovec iov; 510 struct iovec iov;
448 QuicTime timestamp(QuicTime::Zero()); 511 QuicTime timestamp(QuicTime::Zero());
449 while (true) { 512 while (true) {
450 iov.iov_base = buffer; 513 iov.iov_base = buffer;
451 iov.iov_len = arraysize(buffer); 514 iov.iov_len = arraysize(buffer);
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 return true; 669 return true;
607 } 670 }
608 frame_len_ -= len; 671 frame_len_ -= len;
609 // Ignore fin_ while there is more data coming, if frame_len_ > 0. 672 // Ignore fin_ while there is more data coming, if frame_len_ > 0.
610 spdy_session_->OnStreamFrameData(stream_id, data, len, 673 spdy_session_->OnStreamFrameData(stream_id, data, len,
611 frame_len_ > 0 ? false : fin_); 674 frame_len_ > 0 ? false : fin_);
612 return true; 675 return true;
613 } 676 }
614 677
615 } // namespace net 678 } // 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