Index: net/quic/quic_headers_stream.cc |
diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc |
index 7b0f8ec01d9f4134315c09e1053f37ae96e22827..964be3201a4dd72d6bff090482810083eb580a78 100644 |
--- a/net/quic/quic_headers_stream.cc |
+++ b/net/quic/quic_headers_stream.cc |
@@ -20,12 +20,6 @@ using std::string; |
namespace net { |
-namespace { |
- |
-const QuicStreamId kInvalidStreamId = 0; |
- |
-} // namespace |
- |
// A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to |
// the QuicSpdyStream, and closes the connection if any unexpected frames |
// are received. |
@@ -144,7 +138,14 @@ class QuicHeadersStream::SpdyFramerVisitor |
void OnPushPromise(SpdyStreamId stream_id, |
SpdyStreamId promised_stream_id, |
bool end) override { |
- CloseConnection("SPDY PUSH_PROMISE frame received."); |
+ if (!stream_->supports_push_promise()) { |
+ CloseConnection("PUSH_PROMISE not supported."); |
+ return; |
+ } |
+ if (!stream_->IsConnected()) { |
+ return; |
+ } |
+ stream_->OnPushPromise(stream_id, promised_stream_id, end); |
} |
void OnContinuation(SpdyStreamId stream_id, bool end) override {} |
@@ -186,10 +187,14 @@ QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session) |
: ReliableQuicStream(kHeadersStreamId, session), |
spdy_session_(session), |
stream_id_(kInvalidStreamId), |
+ promised_stream_id_(kInvalidStreamId), |
fin_(false), |
frame_len_(0), |
measure_headers_hol_blocking_time_( |
FLAGS_quic_measure_headers_hol_blocking_time), |
+ supports_push_promise_( |
+ session->perspective() == Perspective::IS_CLIENT && |
+ FLAGS_quic_supports_push_promise), |
cur_max_timestamp_(QuicTime::Zero()), |
prev_max_timestamp_(QuicTime::Zero()), |
spdy_framer_(HTTP2), |
@@ -296,10 +301,25 @@ void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id, |
} |
} |
DCHECK_EQ(kInvalidStreamId, stream_id_); |
+ DCHECK_EQ(kInvalidStreamId, promised_stream_id_); |
stream_id_ = stream_id; |
fin_ = fin; |
} |
+void QuicHeadersStream::OnPushPromise(SpdyStreamId stream_id, |
+ SpdyStreamId promised_stream_id, |
+ bool end) { |
+ if (!supports_push_promise_) { |
+ CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, |
+ "SPDY PUSH_PROMISE not supported."); |
+ return; |
+ } |
+ DCHECK_EQ(kInvalidStreamId, stream_id_); |
+ DCHECK_EQ(kInvalidStreamId, promised_stream_id_); |
+ stream_id_ = stream_id; |
+ promised_stream_id_ = promised_stream_id; |
+} |
+ |
void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id, |
const char* header_data, |
size_t len) { |
@@ -322,13 +342,24 @@ void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id, |
prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_); |
cur_max_timestamp_ = QuicTime::Zero(); |
} |
- spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_); |
+ if (promised_stream_id_ == kInvalidStreamId) { |
+ spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_); |
+ } else { |
+ spdy_session_->OnPromiseHeadersComplete(stream_id_, promised_stream_id_, |
+ frame_len_); |
+ } |
// Reset state for the next frame. |
+ promised_stream_id_ = kInvalidStreamId; |
stream_id_ = kInvalidStreamId; |
fin_ = false; |
frame_len_ = 0; |
} else { |
- spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); |
+ if (promised_stream_id_ == kInvalidStreamId) { |
+ spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); |
+ } else { |
+ spdy_session_->OnPromiseHeaders(stream_id_, |
+ StringPiece(header_data, len)); |
+ } |
} |
} |