Index: net/quic/quic_spdy_stream.cc |
diff --git a/net/quic/quic_spdy_stream.cc b/net/quic/quic_spdy_stream.cc |
index 2e099ca5e76c267121f74cf1f75304cf1bc42efd..c946e0c0c95cc5916f9c16ce328100bed7c05ba5 100644 |
--- a/net/quic/quic_spdy_stream.cc |
+++ b/net/quic/quic_spdy_stream.cc |
@@ -183,6 +183,16 @@ void QuicSpdyStream::OnStreamHeadersComplete(bool fin, size_t 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) { |
@@ -193,6 +203,20 @@ void QuicSpdyStream::OnInitialHeadersComplete(bool fin, size_t /*frame_len*/) { |
} |
} |
+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_); |
} |
@@ -208,6 +232,18 @@ void QuicSpdyStream::OnPromiseHeadersComplete( |
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()) { |
@@ -245,6 +281,39 @@ void QuicSpdyStream::OnTrailingHeadersComplete(bool fin, size_t /*frame_len*/) { |
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 || |
version() <= QUIC_VERSION_28) { |
@@ -271,7 +340,8 @@ void QuicSpdyStream::OnClose() { |
} |
bool QuicSpdyStream::FinishedReadingHeaders() const { |
- return headers_decompressed_ && decompressed_headers_.empty(); |
+ return headers_decompressed_ && decompressed_headers_.empty() && |
+ header_list_.empty(); |
} |
bool QuicSpdyStream::ParseHeaderStatusCode(SpdyHeaderBlock* header, |