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"
11 const size_t SpdyHeadersBlockParser::kMaximumFieldLength
= 16 * 1024;
13 SpdyHeadersBlockParser::SpdyHeadersBlockParser(
14 SpdyMajorVersion spdy_version
,
15 SpdyHeadersHandlerInterface
* handler
) :
16 state_(READING_HEADER_BLOCK_LEN
),
17 length_field_size_(LengthFieldSizeForVersion(spdy_version
)),
18 max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version
)),
19 remaining_key_value_pairs_for_frame_(0),
22 // The handler that we set must not be NULL.
23 DCHECK(handler_
!= NULL
);
26 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {}
28 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData(
29 SpdyStreamId stream_id
,
30 const char* headers_data
,
31 size_t headers_data_length
) {
32 if (error_
== NEED_MORE_DATA
) {
37 // If this is the first call with the current header block,
38 // save its stream id.
39 if (state_
== READING_HEADER_BLOCK_LEN
) {
40 stream_id_
= stream_id
;
42 CHECK_EQ(stream_id_
, stream_id
);
44 SpdyPinnableBufferPiece prefix
, key
, value
;
45 // Simultaneously tie lifetimes to the stack, and clear member variables.
46 prefix
.Swap(&headers_block_prefix_
);
49 // Apply the parsing state machine to the remaining prefix
50 // from last invocation, plus newly-available headers data.
51 Reader
reader(prefix
.buffer(), prefix
.length(),
52 headers_data
, headers_data_length
);
53 while (error_
== OK
) {
54 ParserState
next_state(FINISHED_HEADER
);
57 case READING_HEADER_BLOCK_LEN
:
58 next_state
= READING_KEY_LEN
;
59 ParseBlockLength(&reader
);
62 next_state
= READING_KEY
;
63 ParseFieldLength(&reader
);
66 next_state
= READING_VALUE_LEN
;
67 if (!reader
.ReadN(next_field_length_
, &key
)) {
68 error_
= NEED_MORE_DATA
;
71 case READING_VALUE_LEN
:
72 next_state
= READING_VALUE
;
73 ParseFieldLength(&reader
);
76 next_state
= FINISHED_HEADER
;
77 if (!reader
.ReadN(next_field_length_
, &value
)) {
78 error_
= NEED_MORE_DATA
;
80 handler_
->OnHeader(stream_id
, key
, value
);
84 // Prepare for next header or block.
85 if (--remaining_key_value_pairs_for_frame_
> 0) {
86 next_state
= READING_KEY_LEN
;
88 next_state
= READING_HEADER_BLOCK_LEN
;
89 handler_
->OnHeaderBlockEnd(stream_id
);
90 // Expect to have consumed all buffer.
91 if (reader
.Available() != 0) {
92 error_
= TOO_MUCH_DATA
;
97 CHECK(false) << "Not reached.";
103 if (next_state
== READING_HEADER_BLOCK_LEN
) {
104 // We completed reading a full header block. Return to caller.
107 } else if (error_
== NEED_MORE_DATA
) {
108 // We can't continue parsing until more data is available. Make copies of
109 // the key and buffer remainder, in preperation for the next invocation.
110 if (state_
> READING_KEY
) {
114 reader
.ReadN(reader
.Available(), &headers_block_prefix_
);
115 headers_block_prefix_
.Pin();
121 void SpdyHeadersBlockParser::ParseBlockLength(Reader
* reader
) {
122 ParseLength(reader
, &remaining_key_value_pairs_for_frame_
);
124 remaining_key_value_pairs_for_frame_
> max_headers_in_block_
) {
125 error_
= HEADER_BLOCK_TOO_LARGE
;
128 handler_
->OnHeaderBlock(stream_id_
, remaining_key_value_pairs_for_frame_
);
132 void SpdyHeadersBlockParser::ParseFieldLength(Reader
* reader
) {
133 ParseLength(reader
, &next_field_length_
);
135 next_field_length_
> kMaximumFieldLength
) {
136 error_
= HEADER_FIELD_TOO_LARGE
;
140 void SpdyHeadersBlockParser::ParseLength(Reader
* reader
,
141 uint32_t* parsed_length
) {
142 char buffer
[] = {0, 0, 0, 0};
143 if (!reader
->ReadN(length_field_size_
, buffer
)) {
144 error_
= NEED_MORE_DATA
;
147 // Convert from network to host order and return the parsed out integer.
148 if (length_field_size_
== sizeof(uint32_t)) {
149 *parsed_length
= ntohl(*reinterpret_cast<const uint32_t *>(buffer
));
151 *parsed_length
= ntohs(*reinterpret_cast<const uint16_t *>(buffer
));
155 void SpdyHeadersBlockParser::Reset() {
157 SpdyPinnableBufferPiece empty
;
158 headers_block_prefix_
.Swap(&empty
);
161 SpdyPinnableBufferPiece empty
;
165 state_
= READING_HEADER_BLOCK_LEN
;
169 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion(
170 SpdyMajorVersion spdy_version
) {
171 if (spdy_version
< SPDY3
) {
172 return sizeof(uint16_t);
174 return sizeof(uint32_t);
177 size_t SpdyHeadersBlockParser::MaxNumberOfHeadersForVersion(
178 SpdyMajorVersion spdy_version
) {
179 // Account for the length of the header block field.
180 size_t max_bytes_for_headers
=
181 kMaximumFieldLength
- LengthFieldSizeForVersion(spdy_version
);
183 // A minimal size header is twice the length field size (and has a
184 // zero-lengthed key and a zero-lengthed value).
185 return max_bytes_for_headers
/ (2 * LengthFieldSizeForVersion(spdy_version
));