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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 |
OLD | NEW |