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 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 | 362 |
363 // PUSH_PROMISE must not be the last frame sent out, at least followed by | 363 // PUSH_PROMISE must not be the last frame sent out, at least followed by |
364 // response headers. | 364 // response headers. |
365 push_promise.set_fin(false); | 365 push_promise.set_fin(false); |
366 | 366 |
367 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); | 367 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); |
368 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); | 368 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr); |
369 return frame.size(); | 369 return frame.size(); |
370 } | 370 } |
371 | 371 |
| 372 void QuicHeadersStream::WriteDataFrame( |
| 373 QuicStreamId id, |
| 374 StringPiece data, |
| 375 bool fin, |
| 376 QuicAckListenerInterface* ack_notifier_delegate) { |
| 377 SpdyDataIR spdy_data(id, data); |
| 378 spdy_data.set_fin(fin); |
| 379 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); |
| 380 scoped_refptr<ForceHolAckListener> ack_listener; |
| 381 if (ack_notifier_delegate != nullptr) { |
| 382 ack_listener = new ForceHolAckListener(ack_notifier_delegate, |
| 383 frame.size() - data.length()); |
| 384 } |
| 385 // Use buffered writes so that coherence of framing is preserved |
| 386 // between streams. |
| 387 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, |
| 388 ack_listener.get()); |
| 389 } |
| 390 |
372 QuicConsumedData QuicHeadersStream::WritevStreamData( | 391 QuicConsumedData QuicHeadersStream::WritevStreamData( |
373 QuicStreamId id, | 392 QuicStreamId id, |
374 QuicIOVector iov, | 393 QuicIOVector iov, |
375 QuicStreamOffset offset, | 394 QuicStreamOffset offset, |
376 bool fin, | 395 bool fin, |
377 QuicAckListenerInterface* ack_notifier_delegate) { | 396 QuicAckListenerInterface* ack_notifier_delegate) { |
378 const size_t max_len = | 397 const size_t max_len = |
379 kSpdyInitialFrameSizeLimit - SpdyConstants::kDataFrameMinimumSize; | 398 kSpdyInitialFrameSizeLimit - SpdyConstants::kDataFrameMinimumSize; |
380 | 399 |
381 QuicConsumedData result(0, false); | 400 QuicConsumedData result(0, false); |
382 size_t total_length = iov.total_length; | 401 size_t total_length = iov.total_length; |
383 | 402 |
384 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | 403 if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) { |
385 // handles each element of the source iov, the inner loop handles | 404 // Encapsulate the data into HTTP/2 DATA frames. The outer loop |
386 // the possibility of fragmenting eacho of those into multiple DATA | 405 // handles each element of the source iov, the inner loop handles |
387 // frames, as the DATA frames have a max size of 16KB. | 406 // the possibility of fragmenting eacho of those into multiple DATA |
388 for (int i = 0; i < iov.iov_count; i++) { | 407 // frames, as the DATA frames have a max size of 16KB. |
389 size_t offset = 0; | 408 for (int i = 0; i < iov.iov_count; i++) { |
390 const struct iovec* src_iov = &iov.iov[i]; | 409 size_t offset = 0; |
391 do { | 410 const struct iovec* src_iov = &iov.iov[i]; |
392 size_t len = | 411 do { |
393 std::min(std::min(src_iov->iov_len - offset, max_len), total_length); | 412 size_t len = std::min(std::min(src_iov->iov_len - offset, max_len), |
394 char* data = static_cast<char*>(src_iov->iov_base) + offset; | 413 total_length); |
395 SpdyDataIR spdy_data(id, StringPiece(data, len)); | 414 char* data = static_cast<char*>(src_iov->iov_base) + offset; |
396 offset += len; | 415 SpdyDataIR spdy_data(id, StringPiece(data, len)); |
397 // fin handling, set it only it only very last generated HTTP/2 | 416 offset += len; |
398 // DATA frame. | 417 // fin handling, only set it for the final HTTP/2 DATA frame. |
399 bool last_iov = i == iov.iov_count - 1; | 418 bool last_iov = i == iov.iov_count - 1; |
400 bool last_fragment_within_iov = offset >= src_iov->iov_len; | 419 bool last_fragment_within_iov = offset >= src_iov->iov_len; |
401 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | 420 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; |
402 spdy_data.set_fin(frame_fin); | 421 spdy_data.set_fin(frame_fin); |
403 if (frame_fin) { | 422 if (frame_fin) { |
404 result.fin_consumed = true; | 423 result.fin_consumed = true; |
405 } | 424 } |
406 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); | 425 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); |
407 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " | 426 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " |
408 << len << " fin " << spdy_data.fin() << " remaining " | 427 << len << " fin " << spdy_data.fin() << " remaining " |
409 << src_iov->iov_len - offset; | 428 << src_iov->iov_len - offset; |
410 | 429 |
411 scoped_refptr<ForceHolAckListener> ack_listener; | 430 scoped_refptr<ForceHolAckListener> ack_listener; |
412 if (ack_notifier_delegate != nullptr) { | 431 if (ack_notifier_delegate != nullptr) { |
413 ack_listener = | 432 ack_listener = new ForceHolAckListener(ack_notifier_delegate, |
414 new ForceHolAckListener(ack_notifier_delegate, frame.size() - len); | 433 frame.size() - len); |
415 } | 434 } |
416 | 435 |
417 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, | 436 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, |
418 ack_listener.get()); | 437 ack_listener.get()); |
419 result.bytes_consumed += len; | 438 result.bytes_consumed += len; |
420 total_length -= len; | 439 total_length -= len; |
421 if (total_length <= 0) { | 440 if (total_length <= 0) { |
422 return result; | 441 return result; |
423 } | 442 } |
424 } while (offset < src_iov->iov_len); | 443 } while (offset < src_iov->iov_len); |
| 444 } |
| 445 } else { |
| 446 if (total_length == 0 && fin) { |
| 447 WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate); |
| 448 result.fin_consumed = true; |
| 449 return result; |
| 450 } |
| 451 |
| 452 // Encapsulate the data into HTTP/2 DATA frames. The outer loop |
| 453 // handles each element of the source iov, the inner loop handles |
| 454 // the possibility of fragmenting each of those into multiple DATA |
| 455 // frames, as the DATA frames have a max size of 16KB. |
| 456 for (int i = 0; i < iov.iov_count; i++) { |
| 457 size_t src_iov_offset = 0; |
| 458 const struct iovec* src_iov = &iov.iov[i]; |
| 459 do { |
| 460 if (queued_data_bytes() > 0) { |
| 461 // Limit the amount of buffering to the minimum needed to |
| 462 // preserve framing. |
| 463 return result; |
| 464 } |
| 465 size_t len = std::min( |
| 466 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); |
| 467 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; |
| 468 src_iov_offset += len; |
| 469 offset += len; |
| 470 // fin handling, only set it for the final HTTP/2 DATA frame. |
| 471 bool last_iov = i == iov.iov_count - 1; |
| 472 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; |
| 473 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; |
| 474 WriteDataFrame(id, StringPiece(data, len), frame_fin, |
| 475 ack_notifier_delegate); |
| 476 result.bytes_consumed += len; |
| 477 if (frame_fin) { |
| 478 result.fin_consumed = true; |
| 479 } |
| 480 DCHECK_GE(total_length, len); |
| 481 total_length -= len; |
| 482 if (total_length <= 0) { |
| 483 return result; |
| 484 } |
| 485 } while (src_iov_offset < src_iov->iov_len); |
| 486 } |
425 } | 487 } |
| 488 |
426 return result; | 489 return result; |
427 } | 490 } |
428 | 491 |
429 void QuicHeadersStream::OnDataAvailable() { | 492 void QuicHeadersStream::OnDataAvailable() { |
430 char buffer[1024]; | 493 char buffer[1024]; |
431 struct iovec iov; | 494 struct iovec iov; |
432 QuicTime timestamp(QuicTime::Zero()); | 495 QuicTime timestamp(QuicTime::Zero()); |
433 while (true) { | 496 while (true) { |
434 iov.iov_base = buffer; | 497 iov.iov_base = buffer; |
435 iov.iov_len = arraysize(buffer); | 498 iov.iov_len = arraysize(buffer); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 return true; | 653 return true; |
591 } | 654 } |
592 frame_len_ -= len; | 655 frame_len_ -= len; |
593 // Ignore fin_ while there is more data coming, if frame_len_ > 0. | 656 // Ignore fin_ while there is more data coming, if frame_len_ > 0. |
594 spdy_session_->OnStreamFrameData(stream_id, data, len, | 657 spdy_session_->OnStreamFrameData(stream_id, data, len, |
595 frame_len_ > 0 ? false : fin_); | 658 frame_len_ > 0 ? false : fin_); |
596 return true; | 659 return true; |
597 } | 660 } |
598 | 661 |
599 } // namespace net | 662 } // namespace net |
OLD | NEW |