1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/spdy_headers_block_parser.h"
7 #include "base/sys_byteorder.h"
12 // 0 is invalid according to both the SPDY 3.1 and HTTP/2 specifications.
13 const SpdyStreamId kInvalidStreamId
= 0;
15 } // anonymous namespace
17 const size_t SpdyHeadersBlockParser::kMaximumFieldLength
= 16 * 1024;
19 SpdyHeadersBlockParser::SpdyHeadersBlockParser(
20 SpdyMajorVersion spdy_version
,
21 SpdyHeadersHandlerInterface
* handler
)
22 : state_(READING_HEADER_BLOCK_LEN
),
23 length_field_size_(LengthFieldSizeForVersion(spdy_version
)),
24 max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version
)),
25 total_bytes_received_(0),
26 remaining_key_value_pairs_for_frame_(0),
28 stream_id_(kInvalidStreamId
),
29 error_(NO_PARSER_ERROR
),
30 spdy_version_(spdy_version
) {
31 // The handler that we set must not be NULL.
32 DCHECK(handler_
!= NULL
);
35 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {}
37 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData(
38 SpdyStreamId stream_id
,
39 const char* headers_data
,
40 size_t headers_data_length
) {
41 if (error_
== NEED_MORE_DATA
) {
42 error_
= NO_PARSER_ERROR
;
44 if (error_
!= NO_PARSER_ERROR
) {
45 LOG(DFATAL
) << "Unexpected error: " << error_
;
49 // If this is the first call with the current header block,
50 // save its stream id.
51 if (state_
== READING_HEADER_BLOCK_LEN
&& stream_id_
== kInvalidStreamId
) {
52 stream_id_
= stream_id
;
54 if (stream_id
!= stream_id_
) {
55 LOG(DFATAL
) << "Unexpected stream id: " << stream_id
<< " (expected "
57 error_
= UNEXPECTED_STREAM_ID
;
60 if (stream_id_
== kInvalidStreamId
) {
61 LOG(DFATAL
) << "Expected nonzero stream id, saw: " << stream_id_
;
62 error_
= UNEXPECTED_STREAM_ID
;
65 total_bytes_received_
+= headers_data_length
;
67 SpdyPinnableBufferPiece prefix
, key
, value
;
68 // Simultaneously tie lifetimes to the stack, and clear member variables.
69 prefix
.Swap(&headers_block_prefix_
);
72 // Apply the parsing state machine to the remaining prefix
73 // from last invocation, plus newly-available headers data.
74 Reader
reader(prefix
.buffer(), prefix
.length(),
75 headers_data
, headers_data_length
);
76 while (error_
== NO_PARSER_ERROR
) {
77 ParserState
next_state(FINISHED_HEADER
);
80 case READING_HEADER_BLOCK_LEN
:
81 next_state
= READING_KEY_LEN
;
82 ParseBlockLength(&reader
);
85 next_state
= READING_KEY
;
86 ParseFieldLength(&reader
);
89 next_state
= READING_VALUE_LEN
;
90 if (!reader
.ReadN(next_field_length_
, &key
)) {
91 error_
= NEED_MORE_DATA
;
94 case READING_VALUE_LEN
:
95 next_state
= READING_VALUE
;
96 ParseFieldLength(&reader
);
99 next_state
= FINISHED_HEADER
;
100 if (!reader
.ReadN(next_field_length_
, &value
)) {
101 error_
= NEED_MORE_DATA
;
103 handler_
->OnHeader(key
, value
);
106 case FINISHED_HEADER
:
107 // Prepare for next header or block.
108 if (--remaining_key_value_pairs_for_frame_
> 0) {
109 next_state
= READING_KEY_LEN
;
111 next_state
= READING_HEADER_BLOCK_LEN
;
112 handler_
->OnHeaderBlockEnd(total_bytes_received_
);
113 stream_id_
= kInvalidStreamId
;
114 // Expect to have consumed all buffer.
115 if (reader
.Available() != 0) {
116 error_
= TOO_MUCH_DATA
;
122 if (error_
== NO_PARSER_ERROR
) {
125 if (next_state
== READING_HEADER_BLOCK_LEN
) {
126 // We completed reading a full header block. Return to caller.
127 total_bytes_received_
= 0;
130 } else if (error_
== NEED_MORE_DATA
) {
131 // We can't continue parsing until more data is available. Make copies of
132 // the key and buffer remainder, in preperation for the next invocation.
133 if (state_
> READING_KEY
) {
137 reader
.ReadN(reader
.Available(), &headers_block_prefix_
);
138 headers_block_prefix_
.Pin();
141 return error_
== NO_PARSER_ERROR
;
144 void SpdyHeadersBlockParser::ParseBlockLength(Reader
* reader
) {
145 ParseLength(reader
, &remaining_key_value_pairs_for_frame_
);
146 if (error_
== NO_PARSER_ERROR
&&
147 remaining_key_value_pairs_for_frame_
> max_headers_in_block_
) {
148 error_
= HEADER_BLOCK_TOO_LARGE
;
150 if (error_
== NO_PARSER_ERROR
) {
151 handler_
->OnHeaderBlock(remaining_key_value_pairs_for_frame_
);
155 void SpdyHeadersBlockParser::ParseFieldLength(Reader
* reader
) {
156 ParseLength(reader
, &next_field_length_
);
157 if (error_
== NO_PARSER_ERROR
&& next_field_length_
> kMaximumFieldLength
) {
158 error_
= HEADER_FIELD_TOO_LARGE
;
162 void SpdyHeadersBlockParser::ParseLength(Reader
* reader
,
163 uint32_t* parsed_length
) {
164 char buffer
[] = {0, 0, 0, 0};
165 if (!reader
->ReadN(length_field_size_
, buffer
)) {
166 error_
= NEED_MORE_DATA
;
169 // Convert from network to host order and return the parsed out integer.
170 if (length_field_size_
== sizeof(uint32_t)) {
171 *parsed_length
= ntohl(*reinterpret_cast<const uint32_t *>(buffer
));
173 *parsed_length
= ntohs(*reinterpret_cast<const uint16_t *>(buffer
));
177 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion(
178 SpdyMajorVersion spdy_version
) {
179 if (spdy_version
< SPDY3
) {
180 return sizeof(uint16_t);
182 return sizeof(uint32_t);
185 size_t SpdyHeadersBlockParser::MaxNumberOfHeadersForVersion(
186 SpdyMajorVersion spdy_version
) {
187 // Account for the length of the header block field.
188 size_t max_bytes_for_headers
=
189 kMaximumFieldLength
- LengthFieldSizeForVersion(spdy_version
);
191 // A minimal size header is twice the length field size (and has a
192 // zero-lengthed key and a zero-lengthed value).
193 return max_bytes_for_headers
/ (2 * LengthFieldSizeForVersion(spdy_version
));