| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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_spdy_session.h" | 5 #include "net/quic/core/quic_spdy_session.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstdint> | 8 #include <cstdint> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "net/quic/core/quic_flags.h" | 12 #include "net/quic/core/quic_flags.h" |
| 13 #include "net/quic/core/quic_headers_stream.h" | 13 #include "net/quic/core/quic_headers_stream.h" |
| 14 #include "net/quic/platform/api/quic_bug_tracker.h" | 14 #include "net/quic/platform/api/quic_bug_tracker.h" |
| 15 #include "net/quic/platform/api/quic_logging.h" | 15 #include "net/quic/platform/api/quic_logging.h" |
| 16 #include "net/quic/platform/api/quic_str_cat.h" | 16 #include "net/quic/platform/api/quic_str_cat.h" |
| 17 | 17 |
| 18 using base::StringPiece; | |
| 19 using std::string; | 18 using std::string; |
| 20 | 19 |
| 21 namespace net { | 20 namespace net { |
| 22 | 21 |
| 23 namespace { | 22 namespace { |
| 24 | 23 |
| 25 class HeaderTableDebugVisitor | 24 class HeaderTableDebugVisitor |
| 26 : public HpackHeaderTable::DebugVisitorInterface { | 25 : public HpackHeaderTable::DebugVisitorInterface { |
| 27 public: | 26 public: |
| 28 HeaderTableDebugVisitor(const QuicClock* clock, | 27 HeaderTableDebugVisitor(const QuicClock* clock, |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 SpdyPriority priority, | 402 SpdyPriority priority, |
| 404 QuicReferenceCountedPointer<QuicAckListenerInterface> | 403 QuicReferenceCountedPointer<QuicAckListenerInterface> |
| 405 ack_notifier_delegate) { | 404 ack_notifier_delegate) { |
| 406 SpdyHeadersIR headers_frame(id, std::move(headers)); | 405 SpdyHeadersIR headers_frame(id, std::move(headers)); |
| 407 headers_frame.set_fin(fin); | 406 headers_frame.set_fin(fin); |
| 408 if (perspective() == Perspective::IS_CLIENT) { | 407 if (perspective() == Perspective::IS_CLIENT) { |
| 409 headers_frame.set_has_priority(true); | 408 headers_frame.set_has_priority(true); |
| 410 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority)); | 409 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority)); |
| 411 } | 410 } |
| 412 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame)); | 411 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame)); |
| 413 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()), | 412 headers_stream_->WriteOrBufferData( |
| 414 false, std::move(ack_notifier_delegate)); | 413 QuicStringPiece(frame.data(), frame.size()), false, |
| 414 std::move(ack_notifier_delegate)); |
| 415 return frame.size(); | 415 return frame.size(); |
| 416 } | 416 } |
| 417 | 417 |
| 418 size_t QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id, | 418 size_t QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id, |
| 419 QuicStreamId promised_stream_id, | 419 QuicStreamId promised_stream_id, |
| 420 SpdyHeaderBlock headers) { | 420 SpdyHeaderBlock headers) { |
| 421 if (perspective() == Perspective::IS_CLIENT) { | 421 if (perspective() == Perspective::IS_CLIENT) { |
| 422 QUIC_BUG << "Client shouldn't send PUSH_PROMISE"; | 422 QUIC_BUG << "Client shouldn't send PUSH_PROMISE"; |
| 423 return 0; | 423 return 0; |
| 424 } | 424 } |
| 425 | 425 |
| 426 SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id, | 426 SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id, |
| 427 std::move(headers)); | 427 std::move(headers)); |
| 428 // PUSH_PROMISE must not be the last frame sent out, at least followed by | 428 // PUSH_PROMISE must not be the last frame sent out, at least followed by |
| 429 // response headers. | 429 // response headers. |
| 430 push_promise.set_fin(false); | 430 push_promise.set_fin(false); |
| 431 | 431 |
| 432 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); | 432 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise)); |
| 433 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()), | 433 headers_stream_->WriteOrBufferData( |
| 434 false, nullptr); | 434 QuicStringPiece(frame.data(), frame.size()), false, nullptr); |
| 435 return frame.size(); | 435 return frame.size(); |
| 436 } | 436 } |
| 437 | 437 |
| 438 void QuicSpdySession::WriteDataFrame( | 438 void QuicSpdySession::WriteDataFrame( |
| 439 QuicStreamId id, | 439 QuicStreamId id, |
| 440 StringPiece data, | 440 QuicStringPiece data, |
| 441 bool fin, | 441 bool fin, |
| 442 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { | 442 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { |
| 443 // Note that certain SpdyDataIR constructors perform a deep copy of |data| | 443 // Note that certain SpdyDataIR constructors perform a deep copy of |data| |
| 444 // which should be avoided here. | 444 // which should be avoided here. |
| 445 SpdyDataIR spdy_data(id); | 445 SpdyDataIR spdy_data(id); |
| 446 spdy_data.SetDataShallow(data); | 446 spdy_data.SetDataShallow(data); |
| 447 spdy_data.set_fin(fin); | 447 spdy_data.set_fin(fin); |
| 448 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); | 448 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); |
| 449 QuicReferenceCountedPointer<ForceHolAckListener> force_hol_ack_listener; | 449 QuicReferenceCountedPointer<ForceHolAckListener> force_hol_ack_listener; |
| 450 if (ack_listener != nullptr) { | 450 if (ack_listener != nullptr) { |
| 451 force_hol_ack_listener = new ForceHolAckListener( | 451 force_hol_ack_listener = new ForceHolAckListener( |
| 452 std::move(ack_listener), frame.size() - data.length()); | 452 std::move(ack_listener), frame.size() - data.length()); |
| 453 } | 453 } |
| 454 // Use buffered writes so that coherence of framing is preserved | 454 // Use buffered writes so that coherence of framing is preserved |
| 455 // between streams. | 455 // between streams. |
| 456 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()), | 456 headers_stream_->WriteOrBufferData( |
| 457 false, std::move(force_hol_ack_listener)); | 457 QuicStringPiece(frame.data(), frame.size()), false, |
| 458 std::move(force_hol_ack_listener)); |
| 458 } | 459 } |
| 459 | 460 |
| 460 QuicConsumedData QuicSpdySession::WritevStreamData( | 461 QuicConsumedData QuicSpdySession::WritevStreamData( |
| 461 QuicStreamId id, | 462 QuicStreamId id, |
| 462 QuicIOVector iov, | 463 QuicIOVector iov, |
| 463 QuicStreamOffset offset, | 464 QuicStreamOffset offset, |
| 464 bool fin, | 465 bool fin, |
| 465 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { | 466 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { |
| 466 const size_t max_len = | 467 const size_t max_len = |
| 467 kSpdyInitialFrameSizeLimit - kDataFrameMinimumSize; | 468 kSpdyInitialFrameSizeLimit - kDataFrameMinimumSize; |
| 468 | 469 |
| 469 QuicConsumedData result(0, false); | 470 QuicConsumedData result(0, false); |
| 470 size_t total_length = iov.total_length; | 471 size_t total_length = iov.total_length; |
| 471 | 472 |
| 472 if (total_length == 0 && fin) { | 473 if (total_length == 0 && fin) { |
| 473 WriteDataFrame(id, StringPiece(), true, std::move(ack_listener)); | 474 WriteDataFrame(id, QuicStringPiece(), true, std::move(ack_listener)); |
| 474 result.fin_consumed = true; | 475 result.fin_consumed = true; |
| 475 return result; | 476 return result; |
| 476 } | 477 } |
| 477 | 478 |
| 478 // Encapsulate the data into HTTP/2 DATA frames. The outer loop | 479 // Encapsulate the data into HTTP/2 DATA frames. The outer loop |
| 479 // handles each element of the source iov, the inner loop handles | 480 // handles each element of the source iov, the inner loop handles |
| 480 // the possibility of fragmenting each of those into multiple DATA | 481 // the possibility of fragmenting each of those into multiple DATA |
| 481 // frames, as the DATA frames have a max size of 16KB. | 482 // frames, as the DATA frames have a max size of 16KB. |
| 482 for (int i = 0; i < iov.iov_count; i++) { | 483 for (int i = 0; i < iov.iov_count; i++) { |
| 483 size_t src_iov_offset = 0; | 484 size_t src_iov_offset = 0; |
| 484 const struct iovec* src_iov = &iov.iov[i]; | 485 const struct iovec* src_iov = &iov.iov[i]; |
| 485 do { | 486 do { |
| 486 if (headers_stream_->queued_data_bytes() > 0) { | 487 if (headers_stream_->queued_data_bytes() > 0) { |
| 487 // Limit the amount of buffering to the minimum needed to | 488 // Limit the amount of buffering to the minimum needed to |
| 488 // preserve framing. | 489 // preserve framing. |
| 489 return result; | 490 return result; |
| 490 } | 491 } |
| 491 size_t len = std::min( | 492 size_t len = std::min( |
| 492 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); | 493 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); |
| 493 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; | 494 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; |
| 494 src_iov_offset += len; | 495 src_iov_offset += len; |
| 495 offset += len; | 496 offset += len; |
| 496 // fin handling, only set it for the final HTTP/2 DATA frame. | 497 // fin handling, only set it for the final HTTP/2 DATA frame. |
| 497 bool last_iov = i == iov.iov_count - 1; | 498 bool last_iov = i == iov.iov_count - 1; |
| 498 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; | 499 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; |
| 499 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; | 500 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; |
| 500 WriteDataFrame(id, StringPiece(data, len), frame_fin, ack_listener); | 501 WriteDataFrame(id, QuicStringPiece(data, len), frame_fin, ack_listener); |
| 501 result.bytes_consumed += len; | 502 result.bytes_consumed += len; |
| 502 if (frame_fin) { | 503 if (frame_fin) { |
| 503 result.fin_consumed = true; | 504 result.fin_consumed = true; |
| 504 } | 505 } |
| 505 DCHECK_GE(total_length, len); | 506 DCHECK_GE(total_length, len); |
| 506 total_length -= len; | 507 total_length -= len; |
| 507 if (total_length <= 0) { | 508 if (total_length <= 0) { |
| 508 return result; | 509 return result; |
| 509 } | 510 } |
| 510 } while (src_iov_offset < src_iov->iov_len); | 511 } while (src_iov_offset < src_iov->iov_len); |
| 511 } | 512 } |
| 512 | 513 |
| 513 return result; | 514 return result; |
| 514 } | 515 } |
| 515 | 516 |
| 516 size_t QuicSpdySession::SendMaxHeaderListSize(size_t value) { | 517 size_t QuicSpdySession::SendMaxHeaderListSize(size_t value) { |
| 517 SpdySettingsIR settings_frame; | 518 SpdySettingsIR settings_frame; |
| 518 settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value); | 519 settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value); |
| 519 | 520 |
| 520 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame)); | 521 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame)); |
| 521 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()), | 522 headers_stream_->WriteOrBufferData( |
| 522 false, nullptr); | 523 QuicStringPiece(frame.data(), frame.size()), false, nullptr); |
| 523 return frame.size(); | 524 return frame.size(); |
| 524 } | 525 } |
| 525 | 526 |
| 526 void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) { | 527 void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) { |
| 527 // Implemented in Chromium for stats tracking. | 528 // Implemented in Chromium for stats tracking. |
| 528 } | 529 } |
| 529 | 530 |
| 530 void QuicSpdySession::RegisterStreamPriority(QuicStreamId id, | 531 void QuicSpdySession::RegisterStreamPriority(QuicStreamId id, |
| 531 SpdyPriority priority) { | 532 SpdyPriority priority) { |
| 532 write_blocked_streams()->RegisterStream(id, priority); | 533 write_blocked_streams()->RegisterStream(id, priority); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 void QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id, | 594 void QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id, |
| 594 const char* data, | 595 const char* data, |
| 595 size_t len, | 596 size_t len, |
| 596 bool fin) { | 597 bool fin) { |
| 597 QuicSpdyStream* stream = GetSpdyDataStream(stream_id); | 598 QuicSpdyStream* stream = GetSpdyDataStream(stream_id); |
| 598 if (stream == nullptr) { | 599 if (stream == nullptr) { |
| 599 return; | 600 return; |
| 600 } | 601 } |
| 601 const QuicStreamOffset offset = | 602 const QuicStreamOffset offset = |
| 602 stream->flow_controller()->highest_received_byte_offset(); | 603 stream->flow_controller()->highest_received_byte_offset(); |
| 603 const QuicStreamFrame frame(stream_id, fin, offset, StringPiece(data, len)); | 604 const QuicStreamFrame frame(stream_id, fin, offset, |
| 605 QuicStringPiece(data, len)); |
| 604 QUIC_DVLOG(1) << "De-encapsulating DATA frame for stream " << stream_id | 606 QUIC_DVLOG(1) << "De-encapsulating DATA frame for stream " << stream_id |
| 605 << " offset " << offset << " len " << len << " fin " << fin; | 607 << " offset " << offset << " len " << len << " fin " << fin; |
| 606 OnStreamFrame(frame); | 608 OnStreamFrame(frame); |
| 607 } | 609 } |
| 608 | 610 |
| 609 bool QuicSpdySession::ShouldReleaseHeadersStreamSequencerBuffer() { | 611 bool QuicSpdySession::ShouldReleaseHeadersStreamSequencerBuffer() { |
| 610 return false; | 612 return false; |
| 611 } | 613 } |
| 612 | 614 |
| 613 void QuicSpdySession::OnHeaders(SpdyStreamId stream_id, | 615 void QuicSpdySession::OnHeaders(SpdyStreamId stream_id, |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 set_max_uncompressed_header_bytes); | 745 set_max_uncompressed_header_bytes); |
| 744 } | 746 } |
| 745 | 747 |
| 746 void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error, | 748 void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error, |
| 747 const string& details) { | 749 const string& details) { |
| 748 connection()->CloseConnection( | 750 connection()->CloseConnection( |
| 749 error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 751 error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
| 750 } | 752 } |
| 751 | 753 |
| 752 } // namespace net | 754 } // namespace net |
| OLD | NEW |