| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 QuicIOVector iov, | 395 QuicIOVector iov, |
| 396 QuicStreamOffset offset, | 396 QuicStreamOffset offset, |
| 397 bool fin, | 397 bool fin, |
| 398 QuicAckListenerInterface* ack_notifier_delegate) { | 398 QuicAckListenerInterface* ack_notifier_delegate) { |
| 399 const size_t max_len = kSpdyInitialFrameSizeLimit - | 399 const size_t max_len = kSpdyInitialFrameSizeLimit - |
| 400 SpdyConstants::GetDataFrameMinimumSize(HTTP2); | 400 SpdyConstants::GetDataFrameMinimumSize(HTTP2); |
| 401 | 401 |
| 402 QuicConsumedData result(0, false); | 402 QuicConsumedData result(0, false); |
| 403 size_t total_length = iov.total_length; | 403 size_t total_length = iov.total_length; |
| 404 | 404 |
| 405 if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) { | 405 if (total_length == 0 && fin) { |
| 406 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | 406 WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate); |
| 407 // handles each element of the source iov, the inner loop handles | 407 result.fin_consumed = true; |
| 408 // the possibility of fragmenting eacho of those into multiple DATA | 408 return result; |
| 409 // frames, as the DATA frames have a max size of 16KB. | 409 } |
| 410 for (int i = 0; i < iov.iov_count; i++) { | |
| 411 size_t offset = 0; | |
| 412 const struct iovec* src_iov = &iov.iov[i]; | |
| 413 do { | |
| 414 size_t len = std::min(std::min(src_iov->iov_len - offset, max_len), | |
| 415 total_length); | |
| 416 char* data = static_cast<char*>(src_iov->iov_base) + offset; | |
| 417 SpdyDataIR spdy_data(id, StringPiece(data, len)); | |
| 418 offset += len; | |
| 419 // fin handling, only set it for the final HTTP/2 DATA frame. | |
| 420 bool last_iov = i == iov.iov_count - 1; | |
| 421 bool last_fragment_within_iov = offset >= src_iov->iov_len; | |
| 422 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | |
| 423 spdy_data.set_fin(frame_fin); | |
| 424 if (frame_fin) { | |
| 425 result.fin_consumed = true; | |
| 426 } | |
| 427 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); | |
| 428 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " | |
| 429 << len << " fin " << spdy_data.fin() << " remaining " | |
| 430 << src_iov->iov_len - offset; | |
| 431 | 410 |
| 432 scoped_refptr<ForceHolAckListener> ack_listener; | 411 // Encapsulate the data into HTTP/2 DATA frames. The outer loop |
| 433 if (ack_notifier_delegate != nullptr) { | 412 // handles each element of the source iov, the inner loop handles |
| 434 ack_listener = new ForceHolAckListener(ack_notifier_delegate, | 413 // the possibility of fragmenting each of those into multiple DATA |
| 435 frame.size() - len); | 414 // frames, as the DATA frames have a max size of 16KB. |
| 436 } | 415 for (int i = 0; i < iov.iov_count; i++) { |
| 437 | 416 size_t src_iov_offset = 0; |
| 438 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, | 417 const struct iovec* src_iov = &iov.iov[i]; |
| 439 ack_listener.get()); | 418 do { |
| 440 result.bytes_consumed += len; | 419 if (queued_data_bytes() > 0) { |
| 441 total_length -= len; | 420 // Limit the amount of buffering to the minimum needed to |
| 442 if (total_length <= 0) { | 421 // preserve framing. |
| 443 return result; | 422 return result; |
| 444 } | 423 } |
| 445 } while (offset < src_iov->iov_len); | 424 size_t len = std::min( |
| 446 } | 425 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); |
| 447 } else { | 426 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; |
| 448 if (total_length == 0 && fin) { | 427 src_iov_offset += len; |
| 449 WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate); | 428 offset += len; |
| 450 result.fin_consumed = true; | 429 // fin handling, only set it for the final HTTP/2 DATA frame. |
| 451 return result; | 430 bool last_iov = i == iov.iov_count - 1; |
| 452 } | 431 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; |
| 453 | 432 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; |
| 454 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | 433 WriteDataFrame(id, StringPiece(data, len), frame_fin, |
| 455 // handles each element of the source iov, the inner loop handles | 434 ack_notifier_delegate); |
| 456 // the possibility of fragmenting each of those into multiple DATA | 435 result.bytes_consumed += len; |
| 457 // frames, as the DATA frames have a max size of 16KB. | 436 if (frame_fin) { |
| 458 for (int i = 0; i < iov.iov_count; i++) { | 437 result.fin_consumed = true; |
| 459 size_t src_iov_offset = 0; | 438 } |
| 460 const struct iovec* src_iov = &iov.iov[i]; | 439 DCHECK_GE(total_length, len); |
| 461 do { | 440 total_length -= len; |
| 462 if (queued_data_bytes() > 0) { | 441 if (total_length <= 0) { |
| 463 // Limit the amount of buffering to the minimum needed to | 442 return result; |
| 464 // preserve framing. | 443 } |
| 465 return result; | 444 } while (src_iov_offset < src_iov->iov_len); |
| 466 } | |
| 467 size_t len = std::min( | |
| 468 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); | |
| 469 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; | |
| 470 src_iov_offset += len; | |
| 471 offset += len; | |
| 472 // fin handling, only set it for the final HTTP/2 DATA frame. | |
| 473 bool last_iov = i == iov.iov_count - 1; | |
| 474 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; | |
| 475 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | |
| 476 WriteDataFrame(id, StringPiece(data, len), frame_fin, | |
| 477 ack_notifier_delegate); | |
| 478 result.bytes_consumed += len; | |
| 479 if (frame_fin) { | |
| 480 result.fin_consumed = true; | |
| 481 } | |
| 482 DCHECK_GE(total_length, len); | |
| 483 total_length -= len; | |
| 484 if (total_length <= 0) { | |
| 485 return result; | |
| 486 } | |
| 487 } while (src_iov_offset < src_iov->iov_len); | |
| 488 } | |
| 489 } | 445 } |
| 490 | 446 |
| 491 return result; | 447 return result; |
| 492 } | 448 } |
| 493 | 449 |
| 494 void QuicHeadersStream::OnDataAvailable() { | 450 void QuicHeadersStream::OnDataAvailable() { |
| 495 char buffer[1024]; | 451 char buffer[1024]; |
| 496 struct iovec iov; | 452 struct iovec iov; |
| 497 QuicTime timestamp(QuicTime::Zero()); | 453 QuicTime timestamp(QuicTime::Zero()); |
| 498 while (true) { | 454 while (true) { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 return true; | 611 return true; |
| 656 } | 612 } |
| 657 frame_len_ -= len; | 613 frame_len_ -= len; |
| 658 // Ignore fin_ while there is more data coming, if frame_len_ > 0. | 614 // Ignore fin_ while there is more data coming, if frame_len_ > 0. |
| 659 spdy_session_->OnStreamFrameData(stream_id, data, len, | 615 spdy_session_->OnStreamFrameData(stream_id, data, len, |
| 660 frame_len_ > 0 ? false : fin_); | 616 frame_len_ > 0 ? false : fin_); |
| 661 return true; | 617 return true; |
| 662 } | 618 } |
| 663 | 619 |
| 664 } // namespace net | 620 } // namespace net |
| OLD | NEW |