| Index: net/quic/quic_spdy_stream.cc
|
| diff --git a/net/quic/quic_spdy_stream.cc b/net/quic/quic_spdy_stream.cc
|
| deleted file mode 100644
|
| index b4cc7b6baad44d7071dea92c3589886dd2badaa9..0000000000000000000000000000000000000000
|
| --- a/net/quic/quic_spdy_stream.cc
|
| +++ /dev/null
|
| @@ -1,418 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/quic/quic_spdy_stream.h"
|
| -
|
| -#include <utility>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "net/quic/quic_bug_tracker.h"
|
| -#include "net/quic/quic_spdy_session.h"
|
| -#include "net/quic/quic_utils.h"
|
| -#include "net/quic/quic_write_blocked_list.h"
|
| -#include "net/quic/spdy_utils.h"
|
| -
|
| -using base::IntToString;
|
| -using base::StringPiece;
|
| -using std::min;
|
| -using std::string;
|
| -
|
| -namespace net {
|
| -
|
| -#define ENDPOINT \
|
| - (session()->perspective() == Perspective::IS_SERVER ? "Server: " : "Client:" \
|
| - " ")
|
| -
|
| -QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session)
|
| - : ReliableQuicStream(id, spdy_session),
|
| - spdy_session_(spdy_session),
|
| - visitor_(nullptr),
|
| - headers_decompressed_(false),
|
| - priority_(kDefaultPriority),
|
| - trailers_decompressed_(false),
|
| - trailers_delivered_(false) {
|
| - DCHECK_NE(kCryptoStreamId, id);
|
| - // Don't receive any callbacks from the sequencer until headers
|
| - // are complete.
|
| - sequencer()->SetBlockedUntilFlush();
|
| - spdy_session_->RegisterStreamPriority(id, priority_);
|
| -}
|
| -
|
| -QuicSpdyStream::~QuicSpdyStream() {
|
| - if (spdy_session_ != nullptr) {
|
| - spdy_session_->UnregisterStreamPriority(id());
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::CloseWriteSide() {
|
| - if (!fin_received() && !rst_received() && sequencer()->ignore_read_data() &&
|
| - !rst_sent()) {
|
| - DCHECK(fin_sent());
|
| - // Tell the peer to stop sending further data.
|
| - DVLOG(1) << ENDPOINT << "Send QUIC_STREAM_NO_ERROR on stream " << id();
|
| - Reset(QUIC_STREAM_NO_ERROR);
|
| - }
|
| -
|
| - ReliableQuicStream::CloseWriteSide();
|
| -}
|
| -
|
| -void QuicSpdyStream::StopReading() {
|
| - if (!fin_received() && !rst_received() && write_side_closed() &&
|
| - !rst_sent()) {
|
| - DCHECK(fin_sent());
|
| - // Tell the peer to stop sending further data.
|
| - DVLOG(1) << ENDPOINT << "Send QUIC_STREAM_NO_ERROR on stream " << id();
|
| - Reset(QUIC_STREAM_NO_ERROR);
|
| - }
|
| - ReliableQuicStream::StopReading();
|
| -}
|
| -
|
| -size_t QuicSpdyStream::WriteHeaders(
|
| - SpdyHeaderBlock header_block,
|
| - bool fin,
|
| - QuicAckListenerInterface* ack_notifier_delegate) {
|
| - size_t bytes_written = spdy_session_->WriteHeaders(
|
| - id(), std::move(header_block), fin, priority_, ack_notifier_delegate);
|
| - if (fin) {
|
| - // TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
|
| - set_fin_sent(true);
|
| - CloseWriteSide();
|
| - }
|
| - return bytes_written;
|
| -}
|
| -
|
| -void QuicSpdyStream::WriteOrBufferBody(
|
| - const string& data,
|
| - bool fin,
|
| - QuicAckListenerInterface* ack_notifier_delegate) {
|
| - WriteOrBufferData(data, fin, ack_notifier_delegate);
|
| -}
|
| -
|
| -size_t QuicSpdyStream::WriteTrailers(
|
| - SpdyHeaderBlock trailer_block,
|
| - QuicAckListenerInterface* ack_notifier_delegate) {
|
| - if (fin_sent()) {
|
| - QUIC_BUG << "Trailers cannot be sent after a FIN.";
|
| - return 0;
|
| - }
|
| -
|
| - // The header block must contain the final offset for this stream, as the
|
| - // trailers may be processed out of order at the peer.
|
| - DVLOG(1) << "Inserting trailer: (" << kFinalOffsetHeaderKey << ", "
|
| - << stream_bytes_written() + queued_data_bytes() << ")";
|
| - trailer_block.insert(std::make_pair(
|
| - kFinalOffsetHeaderKey,
|
| - IntToString(stream_bytes_written() + queued_data_bytes())));
|
| -
|
| - // Write the trailing headers with a FIN, and close stream for writing:
|
| - // trailers are the last thing to be sent on a stream.
|
| - const bool kFin = true;
|
| - size_t bytes_written = spdy_session_->WriteHeaders(
|
| - id(), std::move(trailer_block), kFin, priority_, ack_notifier_delegate);
|
| - set_fin_sent(kFin);
|
| -
|
| - // Trailers are the last thing to be sent on a stream, but if there is still
|
| - // queued data then CloseWriteSide() will cause it never to be sent.
|
| - if (queued_data_bytes() == 0) {
|
| - CloseWriteSide();
|
| - }
|
| -
|
| - return bytes_written;
|
| -}
|
| -
|
| -size_t QuicSpdyStream::Readv(const struct iovec* iov, size_t iov_len) {
|
| - DCHECK(FinishedReadingHeaders());
|
| - return sequencer()->Readv(iov, iov_len);
|
| -}
|
| -
|
| -int QuicSpdyStream::GetReadableRegions(iovec* iov, size_t iov_len) const {
|
| - DCHECK(FinishedReadingHeaders());
|
| - return sequencer()->GetReadableRegions(iov, iov_len);
|
| -}
|
| -
|
| -void QuicSpdyStream::MarkConsumed(size_t num_bytes) {
|
| - DCHECK(FinishedReadingHeaders());
|
| - return sequencer()->MarkConsumed(num_bytes);
|
| -}
|
| -
|
| -bool QuicSpdyStream::IsDoneReading() const {
|
| - bool done_reading_headers = FinishedReadingHeaders();
|
| - bool done_reading_body = sequencer()->IsClosed();
|
| - bool done_reading_trailers = FinishedReadingTrailers();
|
| - return done_reading_headers && done_reading_body && done_reading_trailers;
|
| -}
|
| -
|
| -bool QuicSpdyStream::HasBytesToRead() const {
|
| - bool headers_to_read = !decompressed_headers_.empty();
|
| - bool body_to_read = sequencer()->HasBytesToRead();
|
| - bool trailers_to_read = !decompressed_trailers_.empty();
|
| - return headers_to_read || body_to_read || trailers_to_read;
|
| -}
|
| -
|
| -void QuicSpdyStream::MarkHeadersConsumed(size_t bytes_consumed) {
|
| - decompressed_headers_.erase(0, bytes_consumed);
|
| - if (FinishedReadingHeaders()) {
|
| - sequencer()->SetUnblocked();
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::MarkTrailersConsumed(size_t bytes_consumed) {
|
| - decompressed_trailers_.erase(0, bytes_consumed);
|
| -}
|
| -
|
| -void QuicSpdyStream::MarkTrailersDelivered() {
|
| - trailers_delivered_ = true;
|
| -}
|
| -
|
| -void QuicSpdyStream::ConsumeHeaderList() {
|
| - header_list_.Clear();
|
| - if (FinishedReadingHeaders()) {
|
| - sequencer()->SetUnblocked();
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::SetPriority(SpdyPriority priority) {
|
| - DCHECK_EQ(0u, stream_bytes_written());
|
| - spdy_session_->UpdateStreamPriority(id(), priority);
|
| - priority_ = priority;
|
| -}
|
| -
|
| -void QuicSpdyStream::OnStreamHeaders(StringPiece headers_data) {
|
| - if (!headers_decompressed_) {
|
| - headers_data.AppendToString(&decompressed_headers_);
|
| - } else {
|
| - DCHECK(!trailers_decompressed_);
|
| - headers_data.AppendToString(&decompressed_trailers_);
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) {
|
| - DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective());
|
| - SetPriority(priority);
|
| -}
|
| -
|
| -void QuicSpdyStream::OnStreamHeadersComplete(bool fin, size_t frame_len) {
|
| - if (!headers_decompressed_) {
|
| - OnInitialHeadersComplete(fin, frame_len);
|
| - } else {
|
| - OnTrailingHeadersComplete(fin, frame_len);
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::OnStreamHeaderList(bool fin,
|
| - size_t frame_len,
|
| - const QuicHeaderList& header_list) {
|
| - if (!headers_decompressed_) {
|
| - OnInitialHeadersComplete(fin, frame_len, header_list);
|
| - } else {
|
| - OnTrailingHeadersComplete(fin, frame_len, header_list);
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::OnInitialHeadersComplete(bool fin, size_t /*frame_len*/) {
|
| - headers_decompressed_ = true;
|
| - if (fin) {
|
| - OnStreamFrame(QuicStreamFrame(id(), fin, 0, StringPiece()));
|
| - }
|
| - if (FinishedReadingHeaders()) {
|
| - sequencer()->SetUnblocked();
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::OnInitialHeadersComplete(
|
| - bool fin,
|
| - size_t /*frame_len*/,
|
| - const QuicHeaderList& header_list) {
|
| - headers_decompressed_ = true;
|
| - header_list_ = header_list;
|
| - if (fin) {
|
| - OnStreamFrame(QuicStreamFrame(id(), fin, 0, StringPiece()));
|
| - }
|
| - if (FinishedReadingHeaders()) {
|
| - sequencer()->SetUnblocked();
|
| - }
|
| -}
|
| -
|
| -void QuicSpdyStream::OnPromiseHeaders(StringPiece headers_data) {
|
| - headers_data.AppendToString(&decompressed_headers_);
|
| -}
|
| -
|
| -void QuicSpdyStream::OnPromiseHeadersComplete(
|
| - QuicStreamId /* promised_stream_id */,
|
| - size_t /* frame_len */) {
|
| - // To be overridden in QuicSpdyClientStream. Not supported on
|
| - // server side.
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| -}
|
| -
|
| -void QuicSpdyStream::OnPromiseHeaderList(
|
| - QuicStreamId /* promised_id */,
|
| - size_t /* frame_len */,
|
| - const QuicHeaderList& /*header_list */) {
|
| - // To be overridden in QuicSpdyClientStream. Not supported on
|
| - // server side.
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Promise headers received by server",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| -}
|
| -
|
| -void QuicSpdyStream::OnTrailingHeadersComplete(bool fin, size_t /*frame_len*/) {
|
| - DCHECK(!trailers_decompressed_);
|
| - if (fin_received()) {
|
| - DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id();
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| - }
|
| - if (!fin) {
|
| - DLOG(ERROR) << "Trailers must have FIN set, on stream: " << id();
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| - }
|
| -
|
| - size_t final_byte_offset = 0;
|
| - if (!SpdyUtils::ParseTrailers(decompressed_trailers().data(),
|
| - decompressed_trailers().length(),
|
| - &final_byte_offset, &received_trailers_)) {
|
| - DLOG(ERROR) << "Trailers are malformed: " << id();
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| - }
|
| -
|
| - // The data on this stream ends at |final_byte_offset|.
|
| - DVLOG(1) << "Stream ends at byte offset: " << final_byte_offset
|
| - << " currently read: " << stream_bytes_read();
|
| -
|
| - OnStreamFrame(QuicStreamFrame(id(), fin, final_byte_offset, StringPiece()));
|
| - trailers_decompressed_ = true;
|
| -}
|
| -
|
| -void QuicSpdyStream::OnTrailingHeadersComplete(
|
| - bool fin,
|
| - size_t /*frame_len*/,
|
| - const QuicHeaderList& header_list) {
|
| - DCHECK(!trailers_decompressed_);
|
| - if (fin_received()) {
|
| - DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id();
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers after fin",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| - }
|
| - if (!fin) {
|
| - DLOG(ERROR) << "Trailers must have FIN set, on stream: " << id();
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Fin missing from trailers",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| - }
|
| -
|
| - size_t final_byte_offset = 0;
|
| - if (!SpdyUtils::CopyAndValidateTrailers(header_list, &final_byte_offset,
|
| - &received_trailers_)) {
|
| - DLOG(ERROR) << "Trailers are malformed: " << id();
|
| - session()->connection()->CloseConnection(
|
| - QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed",
|
| - ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
|
| - return;
|
| - }
|
| - OnStreamFrame(QuicStreamFrame(id(), fin, final_byte_offset, StringPiece()));
|
| - trailers_decompressed_ = true;
|
| -}
|
| -
|
| -void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) {
|
| - if (frame.error_code != QUIC_STREAM_NO_ERROR) {
|
| - ReliableQuicStream::OnStreamReset(frame);
|
| - return;
|
| - }
|
| - DVLOG(1) << "Received QUIC_STREAM_NO_ERROR, not discarding response";
|
| - set_rst_received(true);
|
| - MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
|
| - set_stream_error(frame.error_code);
|
| - CloseWriteSide();
|
| -}
|
| -
|
| -void QuicSpdyStream::OnClose() {
|
| - ReliableQuicStream::OnClose();
|
| -
|
| - if (visitor_) {
|
| - Visitor* visitor = visitor_;
|
| - // Calling Visitor::OnClose() may result the destruction of the visitor,
|
| - // so we need to ensure we don't call it again.
|
| - visitor_ = nullptr;
|
| - visitor->OnClose(this);
|
| - }
|
| -}
|
| -
|
| -bool QuicSpdyStream::FinishedReadingHeaders() const {
|
| - return headers_decompressed_ && decompressed_headers_.empty() &&
|
| - header_list_.empty();
|
| -}
|
| -
|
| -bool QuicSpdyStream::ParseHeaderStatusCode(const SpdyHeaderBlock& header,
|
| - int* status_code) const {
|
| - SpdyHeaderBlock::const_iterator it = header.find(":status");
|
| - if (it == header.end()) {
|
| - return false;
|
| - }
|
| - const StringPiece status(it->second);
|
| - if (status.size() != 3) {
|
| - return false;
|
| - }
|
| - // First character must be an integer in range [1,5].
|
| - if (status[0] < '1' || status[0] > '5') {
|
| - return false;
|
| - }
|
| - // The remaining two characters must be integers.
|
| - if (!isdigit(status[1]) || !isdigit(status[2])) {
|
| - return false;
|
| - }
|
| - return StringToInt(status, status_code);
|
| -}
|
| -
|
| -bool QuicSpdyStream::FinishedReadingTrailers() const {
|
| - // If no further trailing headers are expected, and the decompressed trailers
|
| - // (if any) have been consumed, then reading of trailers is finished.
|
| - if (!fin_received()) {
|
| - return false;
|
| - } else if (!trailers_decompressed_) {
|
| - return true;
|
| - } else {
|
| - return trailers_delivered_ && decompressed_trailers_.empty();
|
| - }
|
| -}
|
| -
|
| -SpdyPriority QuicSpdyStream::priority() const {
|
| - return priority_;
|
| -}
|
| -
|
| -void QuicSpdyStream::ClearSession() {
|
| - spdy_session_ = nullptr;
|
| -}
|
| -
|
| -QuicConsumedData QuicSpdyStream::WritevDataInner(
|
| - QuicIOVector iov,
|
| - QuicStreamOffset offset,
|
| - bool fin,
|
| - QuicAckListenerInterface* ack_notifier_delegate) {
|
| - if (spdy_session_->headers_stream() != nullptr &&
|
| - spdy_session_->force_hol_blocking()) {
|
| - return spdy_session_->headers_stream()->WritevStreamData(
|
| - id(), iov, offset, fin, ack_notifier_delegate);
|
| - }
|
| - return ReliableQuicStream::WritevDataInner(iov, offset, fin,
|
| - ack_notifier_delegate);
|
| -}
|
| -
|
| -} // namespace net
|
|
|