Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: net/quic/quic_spdy_stream.cc

Issue 1518483003: QuicSpdyStream supports receiving trailing headers frames. Flag protected by FLAGS_quic_support_tra… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@clean
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_spdy_stream.h ('k') | net/quic/quic_spdy_stream_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « net/quic/quic_spdy_stream.h ('k') | net/quic/quic_spdy_stream_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698