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