| 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/quic_spdy_stream.h" | 5 #include "net/quic/quic_spdy_stream.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "net/quic/quic_spdy_session.h" | 8 #include "net/quic/quic_spdy_session.h" |
| 9 #include "net/quic/quic_utils.h" | 9 #include "net/quic/quic_utils.h" |
| 10 #include "net/quic/quic_write_blocked_list.h" | 10 #include "net/quic/quic_write_blocked_list.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 // priority in the middle. | 27 // priority in the middle. |
| 28 SpdyPriority kDefaultPriority = 3; | 28 SpdyPriority kDefaultPriority = 3; |
| 29 | 29 |
| 30 } // namespace | 30 } // namespace |
| 31 | 31 |
| 32 QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session) | 32 QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session) |
| 33 : ReliableQuicStream(id, spdy_session), | 33 : ReliableQuicStream(id, spdy_session), |
| 34 spdy_session_(spdy_session), | 34 spdy_session_(spdy_session), |
| 35 visitor_(nullptr), | 35 visitor_(nullptr), |
| 36 headers_decompressed_(false), | 36 headers_decompressed_(false), |
| 37 priority_(kDefaultPriority) { | 37 priority_(kDefaultPriority), |
| 38 trailers_decompressed_(false) { |
| 38 DCHECK_NE(kCryptoStreamId, id); | 39 DCHECK_NE(kCryptoStreamId, id); |
| 39 // Don't receive any callbacks from the sequencer until headers | 40 // Don't receive any callbacks from the sequencer until headers |
| 40 // are complete. | 41 // are complete. |
| 41 sequencer()->SetBlockedUntilFlush(); | 42 sequencer()->SetBlockedUntilFlush(); |
| 42 } | 43 } |
| 43 | 44 |
| 44 QuicSpdyStream::~QuicSpdyStream() {} | 45 QuicSpdyStream::~QuicSpdyStream() {} |
| 45 | 46 |
| 46 void QuicSpdyStream::CloseWriteSide() { | 47 void QuicSpdyStream::CloseWriteSide() { |
| 47 if (version() > QUIC_VERSION_28 && !fin_received() && !rst_received() && | 48 if (version() > QUIC_VERSION_28 && !fin_received() && !rst_received() && |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 DCHECK(FinishedReadingHeaders()); | 90 DCHECK(FinishedReadingHeaders()); |
| 90 return sequencer()->GetReadableRegions(iov, iov_len); | 91 return sequencer()->GetReadableRegions(iov, iov_len); |
| 91 } | 92 } |
| 92 | 93 |
| 93 void QuicSpdyStream::MarkConsumed(size_t num_bytes) { | 94 void QuicSpdyStream::MarkConsumed(size_t num_bytes) { |
| 94 DCHECK(FinishedReadingHeaders()); | 95 DCHECK(FinishedReadingHeaders()); |
| 95 return sequencer()->MarkConsumed(num_bytes); | 96 return sequencer()->MarkConsumed(num_bytes); |
| 96 } | 97 } |
| 97 | 98 |
| 98 bool QuicSpdyStream::IsDoneReading() const { | 99 bool QuicSpdyStream::IsDoneReading() const { |
| 99 if (!headers_decompressed_ || !decompressed_headers_.empty()) { | 100 bool done_reading_headers = FinishedReadingHeaders(); |
| 100 return false; | 101 bool done_reading_body = sequencer()->IsClosed(); |
| 101 } | 102 bool done_reading_trailers = FinishedReadingTrailers(); |
| 102 return sequencer()->IsClosed(); | 103 return done_reading_headers && done_reading_body && done_reading_trailers; |
| 103 } | 104 } |
| 104 | 105 |
| 105 bool QuicSpdyStream::HasBytesToRead() const { | 106 bool QuicSpdyStream::HasBytesToRead() const { |
| 106 return !decompressed_headers_.empty() || sequencer()->HasBytesToRead(); | 107 bool headers_to_read = !decompressed_headers_.empty(); |
| 108 bool body_to_read = sequencer()->HasBytesToRead(); |
| 109 bool trailers_to_read = |
| 110 (FLAGS_quic_supports_trailers && !decompressed_trailers_.empty()); |
| 111 return headers_to_read || body_to_read || trailers_to_read; |
| 107 } | 112 } |
| 108 | 113 |
| 109 void QuicSpdyStream::MarkHeadersConsumed(size_t bytes_consumed) { | 114 void QuicSpdyStream::MarkHeadersConsumed(size_t bytes_consumed) { |
| 110 decompressed_headers_.erase(0, bytes_consumed); | 115 decompressed_headers_.erase(0, bytes_consumed); |
| 111 if (FinishedReadingHeaders()) { | 116 if (FinishedReadingHeaders()) { |
| 112 sequencer()->SetUnblocked(); | 117 sequencer()->SetUnblocked(); |
| 113 } | 118 } |
| 114 } | 119 } |
| 115 | 120 |
| 121 void QuicSpdyStream::MarkTrailersConsumed(size_t bytes_consumed) { |
| 122 decompressed_trailers_.erase(0, bytes_consumed); |
| 123 } |
| 124 |
| 116 void QuicSpdyStream::set_priority(SpdyPriority priority) { | 125 void QuicSpdyStream::set_priority(SpdyPriority priority) { |
| 117 DCHECK_EQ(0u, stream_bytes_written()); | 126 DCHECK_EQ(0u, stream_bytes_written()); |
| 118 priority_ = priority; | 127 priority_ = priority; |
| 119 } | 128 } |
| 120 | 129 |
| 121 SpdyPriority QuicSpdyStream::Priority() const { | 130 SpdyPriority QuicSpdyStream::Priority() const { |
| 122 return priority(); | 131 return priority(); |
| 123 } | 132 } |
| 124 | 133 |
| 125 void QuicSpdyStream::OnStreamHeaders(StringPiece headers_data) { | 134 void QuicSpdyStream::OnStreamHeaders(StringPiece headers_data) { |
| 126 headers_data.AppendToString(&decompressed_headers_); | 135 if (!FLAGS_quic_supports_trailers || !headers_decompressed_) { |
| 136 headers_data.AppendToString(&decompressed_headers_); |
| 137 } else { |
| 138 DCHECK(!trailers_decompressed_); |
| 139 headers_data.AppendToString(&decompressed_trailers_); |
| 140 } |
| 127 } | 141 } |
| 128 | 142 |
| 129 void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) { | 143 void QuicSpdyStream::OnStreamHeadersPriority(SpdyPriority priority) { |
| 130 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective()); | 144 DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective()); |
| 131 set_priority(priority); | 145 set_priority(priority); |
| 132 } | 146 } |
| 133 | 147 |
| 134 void QuicSpdyStream::OnStreamHeadersComplete(bool fin, size_t frame_len) { | 148 void QuicSpdyStream::OnStreamHeadersComplete(bool fin, size_t frame_len) { |
| 149 if (!FLAGS_quic_supports_trailers || !headers_decompressed_) { |
| 150 OnInitialHeadersComplete(fin, frame_len); |
| 151 } else { |
| 152 OnTrailingHeadersComplete(fin, frame_len); |
| 153 } |
| 154 } |
| 155 |
| 156 void QuicSpdyStream::OnInitialHeadersComplete(bool fin, size_t /*frame_len*/) { |
| 135 headers_decompressed_ = true; | 157 headers_decompressed_ = true; |
| 136 if (fin) { | 158 if (fin) { |
| 137 OnStreamFrame(QuicStreamFrame(id(), fin, 0, StringPiece())); | 159 OnStreamFrame(QuicStreamFrame(id(), fin, 0, StringPiece())); |
| 138 } | 160 } |
| 139 if (FinishedReadingHeaders()) { | 161 if (FinishedReadingHeaders()) { |
| 140 sequencer()->SetUnblocked(); | 162 sequencer()->SetUnblocked(); |
| 141 } | 163 } |
| 142 } | 164 } |
| 143 | 165 |
| 166 void QuicSpdyStream::OnTrailingHeadersComplete(bool fin, size_t /*frame_len*/) { |
| 167 DCHECK(!trailers_decompressed_); |
| 168 if (fin_received()) { |
| 169 DLOG(ERROR) << "Received Trailers after FIN, on stream: " << id(); |
| 170 session()->CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA); |
| 171 return; |
| 172 } |
| 173 if (!fin) { |
| 174 DLOG(ERROR) << "Trailers must have FIN set, on stream: " << id(); |
| 175 session()->CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA); |
| 176 return; |
| 177 } |
| 178 trailers_decompressed_ = true; |
| 179 } |
| 180 |
| 144 void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { | 181 void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { |
| 145 if (frame.error_code != QUIC_STREAM_NO_ERROR || | 182 if (frame.error_code != QUIC_STREAM_NO_ERROR || |
| 146 version() <= QUIC_VERSION_28) { | 183 version() <= QUIC_VERSION_28) { |
| 147 ReliableQuicStream::OnStreamReset(frame); | 184 ReliableQuicStream::OnStreamReset(frame); |
| 148 return; | 185 return; |
| 149 } | 186 } |
| 150 DVLOG(1) << "Received QUIC_STREAM_NO_ERROR, not discarding response"; | 187 DVLOG(1) << "Received QUIC_STREAM_NO_ERROR, not discarding response"; |
| 151 set_rst_received(true); | 188 set_rst_received(true); |
| 152 MaybeIncreaseHighestReceivedOffset(frame.byte_offset); | 189 MaybeIncreaseHighestReceivedOffset(frame.byte_offset); |
| 153 set_stream_error(frame.error_code); | 190 set_stream_error(frame.error_code); |
| 154 CloseWriteSide(); | 191 CloseWriteSide(); |
| 155 } | 192 } |
| 156 | 193 |
| 157 void QuicSpdyStream::OnClose() { | 194 void QuicSpdyStream::OnClose() { |
| 158 ReliableQuicStream::OnClose(); | 195 ReliableQuicStream::OnClose(); |
| 159 | 196 |
| 160 if (visitor_) { | 197 if (visitor_) { |
| 161 Visitor* visitor = visitor_; | 198 Visitor* visitor = visitor_; |
| 162 // Calling Visitor::OnClose() may result the destruction of the visitor, | 199 // Calling Visitor::OnClose() may result the destruction of the visitor, |
| 163 // so we need to ensure we don't call it again. | 200 // so we need to ensure we don't call it again. |
| 164 visitor_ = nullptr; | 201 visitor_ = nullptr; |
| 165 visitor->OnClose(this); | 202 visitor->OnClose(this); |
| 166 } | 203 } |
| 167 } | 204 } |
| 168 | 205 |
| 169 bool QuicSpdyStream::FinishedReadingHeaders() const { | 206 bool QuicSpdyStream::FinishedReadingHeaders() const { |
| 170 return headers_decompressed_ && decompressed_headers_.empty(); | 207 return headers_decompressed_ && decompressed_headers_.empty(); |
| 171 } | 208 } |
| 172 | 209 |
| 210 bool QuicSpdyStream::FinishedReadingTrailers() const { |
| 211 if (!FLAGS_quic_supports_trailers) { |
| 212 return true; |
| 213 } |
| 214 return trailers_decompressed_ && decompressed_trailers_.empty(); |
| 215 } |
| 216 |
| 173 } // namespace net | 217 } // namespace net |
| OLD | NEW |