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_headers_stream.h" | 5 #include "net/quic/quic_headers_stream.h" |
6 | 6 |
7 #include "base/macros.h" | 7 #include "base/macros.h" |
8 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "net/quic/quic_bug_tracker.h" | 10 #include "net/quic/quic_bug_tracker.h" |
11 #include "net/quic/quic_flags.h" | 11 #include "net/quic/quic_flags.h" |
12 #include "net/quic/quic_headers_stream.h" | 12 #include "net/quic/quic_headers_stream.h" |
13 #include "net/quic/quic_spdy_session.h" | 13 #include "net/quic/quic_spdy_session.h" |
14 #include "net/quic/quic_time.h" | 14 #include "net/quic/quic_time.h" |
15 | 15 |
16 using base::StringPiece; | 16 using base::StringPiece; |
17 using net::HTTP2; | 17 using net::HTTP2; |
18 using net::SpdyFrameType; | 18 using net::SpdyFrameType; |
19 using std::string; | 19 using std::string; |
20 | 20 |
21 namespace net { | 21 namespace net { |
22 | 22 |
23 namespace { | |
24 | |
25 const QuicStreamId kInvalidStreamId = 0; | |
26 | |
27 } // namespace | |
28 | |
29 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to | 23 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to |
30 // the QuicSpdyStream, and closes the connection if any unexpected frames | 24 // the QuicSpdyStream, and closes the connection if any unexpected frames |
31 // are received. | 25 // are received. |
32 class QuicHeadersStream::SpdyFramerVisitor | 26 class QuicHeadersStream::SpdyFramerVisitor |
33 : public SpdyFramerVisitorInterface, | 27 : public SpdyFramerVisitorInterface, |
34 public SpdyFramerDebugVisitorInterface { | 28 public SpdyFramerDebugVisitorInterface { |
35 public: | 29 public: |
36 explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {} | 30 explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {} |
37 | 31 |
38 // SpdyFramerVisitorInterface implementation | 32 // SpdyFramerVisitorInterface implementation |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 stream_->OnHeaders(stream_id, has_priority, priority, fin); | 131 stream_->OnHeaders(stream_id, has_priority, priority, fin); |
138 } | 132 } |
139 | 133 |
140 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override { | 134 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override { |
141 CloseConnection("SPDY WINDOW_UPDATE frame received."); | 135 CloseConnection("SPDY WINDOW_UPDATE frame received."); |
142 } | 136 } |
143 | 137 |
144 void OnPushPromise(SpdyStreamId stream_id, | 138 void OnPushPromise(SpdyStreamId stream_id, |
145 SpdyStreamId promised_stream_id, | 139 SpdyStreamId promised_stream_id, |
146 bool end) override { | 140 bool end) override { |
147 CloseConnection("SPDY PUSH_PROMISE frame received."); | 141 if (!stream_->supports_push_promise()) { |
| 142 CloseConnection("PUSH_PROMISE not supported."); |
| 143 return; |
| 144 } |
| 145 if (!stream_->IsConnected()) { |
| 146 return; |
| 147 } |
| 148 stream_->OnPushPromise(stream_id, promised_stream_id, end); |
148 } | 149 } |
149 | 150 |
150 void OnContinuation(SpdyStreamId stream_id, bool end) override {} | 151 void OnContinuation(SpdyStreamId stream_id, bool end) override {} |
151 | 152 |
152 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override { | 153 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override { |
153 CloseConnection("Unknown frame type received."); | 154 CloseConnection("Unknown frame type received."); |
154 return false; | 155 return false; |
155 } | 156 } |
156 | 157 |
157 // SpdyFramerDebugVisitorInterface implementation | 158 // SpdyFramerDebugVisitorInterface implementation |
(...skipping 21 matching lines...) Expand all Loading... |
179 private: | 180 private: |
180 QuicHeadersStream* stream_; | 181 QuicHeadersStream* stream_; |
181 | 182 |
182 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); | 183 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); |
183 }; | 184 }; |
184 | 185 |
185 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session) | 186 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session) |
186 : ReliableQuicStream(kHeadersStreamId, session), | 187 : ReliableQuicStream(kHeadersStreamId, session), |
187 spdy_session_(session), | 188 spdy_session_(session), |
188 stream_id_(kInvalidStreamId), | 189 stream_id_(kInvalidStreamId), |
| 190 promised_stream_id_(kInvalidStreamId), |
189 fin_(false), | 191 fin_(false), |
190 frame_len_(0), | 192 frame_len_(0), |
191 measure_headers_hol_blocking_time_( | 193 measure_headers_hol_blocking_time_( |
192 FLAGS_quic_measure_headers_hol_blocking_time), | 194 FLAGS_quic_measure_headers_hol_blocking_time), |
| 195 supports_push_promise_( |
| 196 session->perspective() == Perspective::IS_CLIENT && |
| 197 FLAGS_quic_supports_push_promise), |
193 cur_max_timestamp_(QuicTime::Zero()), | 198 cur_max_timestamp_(QuicTime::Zero()), |
194 prev_max_timestamp_(QuicTime::Zero()), | 199 prev_max_timestamp_(QuicTime::Zero()), |
195 spdy_framer_(HTTP2), | 200 spdy_framer_(HTTP2), |
196 spdy_framer_visitor_(new SpdyFramerVisitor(this)) { | 201 spdy_framer_visitor_(new SpdyFramerVisitor(this)) { |
197 spdy_framer_.set_visitor(spdy_framer_visitor_.get()); | 202 spdy_framer_.set_visitor(spdy_framer_visitor_.get()); |
198 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get()); | 203 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get()); |
199 // The headers stream is exempt from connection level flow control. | 204 // The headers stream is exempt from connection level flow control. |
200 DisableConnectionFlowControlForThisStream(); | 205 DisableConnectionFlowControlForThisStream(); |
201 } | 206 } |
202 | 207 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 } | 294 } |
290 spdy_session_->OnStreamHeadersPriority(stream_id, priority); | 295 spdy_session_->OnStreamHeadersPriority(stream_id, priority); |
291 } else { | 296 } else { |
292 if (session()->perspective() == Perspective::IS_SERVER) { | 297 if (session()->perspective() == Perspective::IS_SERVER) { |
293 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | 298 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, |
294 "Client must send priorities."); | 299 "Client must send priorities."); |
295 return; | 300 return; |
296 } | 301 } |
297 } | 302 } |
298 DCHECK_EQ(kInvalidStreamId, stream_id_); | 303 DCHECK_EQ(kInvalidStreamId, stream_id_); |
| 304 DCHECK_EQ(kInvalidStreamId, promised_stream_id_); |
299 stream_id_ = stream_id; | 305 stream_id_ = stream_id; |
300 fin_ = fin; | 306 fin_ = fin; |
301 } | 307 } |
302 | 308 |
| 309 void QuicHeadersStream::OnPushPromise(SpdyStreamId stream_id, |
| 310 SpdyStreamId promised_stream_id, |
| 311 bool end) { |
| 312 if (!supports_push_promise_) { |
| 313 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, |
| 314 "SPDY PUSH_PROMISE not supported."); |
| 315 return; |
| 316 } |
| 317 DCHECK_EQ(kInvalidStreamId, stream_id_); |
| 318 DCHECK_EQ(kInvalidStreamId, promised_stream_id_); |
| 319 stream_id_ = stream_id; |
| 320 promised_stream_id_ = promised_stream_id; |
| 321 } |
| 322 |
303 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id, | 323 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id, |
304 const char* header_data, | 324 const char* header_data, |
305 size_t len) { | 325 size_t len) { |
306 DCHECK_EQ(stream_id_, stream_id); | 326 DCHECK_EQ(stream_id_, stream_id); |
307 if (len == 0) { | 327 if (len == 0) { |
308 DCHECK_NE(0u, stream_id_); | 328 DCHECK_NE(0u, stream_id_); |
309 DCHECK_NE(0u, frame_len_); | 329 DCHECK_NE(0u, frame_len_); |
310 if (measure_headers_hol_blocking_time_) { | 330 if (measure_headers_hol_blocking_time_) { |
311 if (prev_max_timestamp_ > cur_max_timestamp_) { | 331 if (prev_max_timestamp_ > cur_max_timestamp_) { |
312 // prev_max_timestamp_ > cur_max_timestamp_ implies that | 332 // prev_max_timestamp_ > cur_max_timestamp_ implies that |
313 // headers from lower numbered streams actually came off the | 333 // headers from lower numbered streams actually came off the |
314 // wire after headers for the current stream, hence there was | 334 // wire after headers for the current stream, hence there was |
315 // HOL blocking. | 335 // HOL blocking. |
316 QuicTime::Delta delta(prev_max_timestamp_.Subtract(cur_max_timestamp_)); | 336 QuicTime::Delta delta(prev_max_timestamp_.Subtract(cur_max_timestamp_)); |
317 DVLOG(1) << "stream " << stream_id | 337 DVLOG(1) << "stream " << stream_id |
318 << ": Net.QuicSession.HeadersHOLBlockedTime " | 338 << ": Net.QuicSession.HeadersHOLBlockedTime " |
319 << delta.ToMilliseconds(); | 339 << delta.ToMilliseconds(); |
320 spdy_session_->OnHeadersHeadOfLineBlocking(delta); | 340 spdy_session_->OnHeadersHeadOfLineBlocking(delta); |
321 } | 341 } |
322 prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_); | 342 prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_); |
323 cur_max_timestamp_ = QuicTime::Zero(); | 343 cur_max_timestamp_ = QuicTime::Zero(); |
324 } | 344 } |
325 spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_); | 345 if (promised_stream_id_ == kInvalidStreamId) { |
| 346 spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_); |
| 347 } else { |
| 348 spdy_session_->OnPromiseHeadersComplete(stream_id_, promised_stream_id_, |
| 349 frame_len_); |
| 350 } |
326 // Reset state for the next frame. | 351 // Reset state for the next frame. |
| 352 promised_stream_id_ = kInvalidStreamId; |
327 stream_id_ = kInvalidStreamId; | 353 stream_id_ = kInvalidStreamId; |
328 fin_ = false; | 354 fin_ = false; |
329 frame_len_ = 0; | 355 frame_len_ = 0; |
330 } else { | 356 } else { |
331 spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); | 357 if (promised_stream_id_ == kInvalidStreamId) { |
| 358 spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); |
| 359 } else { |
| 360 spdy_session_->OnPromiseHeaders(stream_id_, |
| 361 StringPiece(header_data, len)); |
| 362 } |
332 } | 363 } |
333 } | 364 } |
334 | 365 |
335 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { | 366 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { |
336 frame_len_ += frame_len; | 367 frame_len_ += frame_len; |
337 } | 368 } |
338 | 369 |
339 bool QuicHeadersStream::IsConnected() { | 370 bool QuicHeadersStream::IsConnected() { |
340 return session()->connection()->connected(); | 371 return session()->connection()->connected(); |
341 } | 372 } |
342 | 373 |
343 } // namespace net | 374 } // namespace net |
OLD | NEW |