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 total_bytes_received_(0),
20 remaining_key_value_pairs_for_frame_(0),
23 // The handler that we set must not be NULL.
24 DCHECK(handler_
!= NULL
);
27 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {}
29 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData(
30 SpdyStreamId stream_id
,
31 const char* headers_data
,
32 size_t headers_data_length
) {
33 if (error_
== NEED_MORE_DATA
) {
38 // If this is the first call with the current header block,
39 // save its stream id.
40 if (state_
== READING_HEADER_BLOCK_LEN
) {
41 stream_id_
= stream_id
;
43 CHECK_EQ(stream_id_
, stream_id
);
45 total_bytes_received_
+= headers_data_length
;
47 SpdyPinnableBufferPiece prefix
, key
, value
;
48 // Simultaneously tie lifetimes to the stack, and clear member variables.
49 prefix
.Swap(&headers_block_prefix_
);
52 // Apply the parsing state machine to the remaining prefix
53 // from last invocation, plus newly-available headers data.
54 Reader
reader(prefix
.buffer(), prefix
.length(),
55 headers_data
, headers_data_length
);
56 while (error_
== OK
) {
57 ParserState
next_state(FINISHED_HEADER
);
60 case READING_HEADER_BLOCK_LEN
:
61 next_state
= READING_KEY_LEN
;
62 ParseBlockLength(&reader
);
65 next_state
= READING_KEY
;
66 ParseFieldLength(&reader
);
69 next_state
= READING_VALUE_LEN
;
70 if (!reader
.ReadN(next_field_length_
, &key
)) {
71 error_
= NEED_MORE_DATA
;
74 case READING_VALUE_LEN
:
75 next_state
= READING_VALUE
;
76 ParseFieldLength(&reader
);
79 next_state
= FINISHED_HEADER
;
80 if (!reader
.ReadN(next_field_length_
, &value
)) {
81 error_
= NEED_MORE_DATA
;
83 handler_
->OnHeader(stream_id
, key
, value
);
87 // Prepare for next header or block.
88 if (--remaining_key_value_pairs_for_frame_
> 0) {
89 next_state
= READING_KEY_LEN
;
91 next_state
= READING_HEADER_BLOCK_LEN
;
92 handler_
->OnHeaderBlockEnd(stream_id
, total_bytes_received_
);
93 // Expect to have consumed all buffer.
94 if (reader
.Available() != 0) {
95 error_
= TOO_MUCH_DATA
;
100 CHECK(false) << "Not reached.";
106 if (next_state
== READING_HEADER_BLOCK_LEN
) {
107 // We completed reading a full header block. Return to caller.
108 total_bytes_received_
= 0;
111 } else if (error_
== NEED_MORE_DATA
) {
112 // We can't continue parsing until more data is available. Make copies of
113 // the key and buffer remainder, in preperation for the next invocation.
114 if (state_
> READING_KEY
) {
118 reader
.ReadN(reader
.Available(), &headers_block_prefix_
);
119 headers_block_prefix_
.Pin();
125 void SpdyHeadersBlockParser::ParseBlockLength(Reader
* reader
) {
126 ParseLength(reader
, &remaining_key_value_pairs_for_frame_
);
128 remaining_key_value_pairs_for_frame_
> max_headers_in_block_
) {
129 error_
= HEADER_BLOCK_TOO_LARGE
;
132 handler_
->OnHeaderBlock(stream_id_
, remaining_key_value_pairs_for_frame_
);
136 void SpdyHeadersBlockParser::ParseFieldLength(Reader
* reader
) {
137 ParseLength(reader
, &next_field_length_
);
139 next_field_length_
> kMaximumFieldLength
) {
140 error_
= HEADER_FIELD_TOO_LARGE
;
144 void SpdyHeadersBlockParser::ParseLength(Reader
* reader
,
145 uint32_t* parsed_length
) {
146 char buffer
[] = {0, 0, 0, 0};
147 if (!reader
->ReadN(length_field_size_
, buffer
)) {
148 error_
= NEED_MORE_DATA
;
151 // Convert from network to host order and return the parsed out integer.
152 if (length_field_size_
== sizeof(uint32_t)) {
153 *parsed_length
= ntohl(*reinterpret_cast<const uint32_t *>(buffer
));
155 *parsed_length
= ntohs(*reinterpret_cast<const uint16_t *>(buffer
));
159 void SpdyHeadersBlockParser::Reset() {
161 SpdyPinnableBufferPiece empty
;
162 headers_block_prefix_
.Swap(&empty
);
165 SpdyPinnableBufferPiece empty
;
169 state_
= READING_HEADER_BLOCK_LEN
;
171 total_bytes_received_
= 0;
174 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion(
175 SpdyMajorVersion spdy_version
) {
176 if (spdy_version
< SPDY3
) {
177 return sizeof(uint16_t);
179 return sizeof(uint32_t);
182 size_t SpdyHeadersBlockParser::MaxNumberOfHeadersForVersion(
183 SpdyMajorVersion spdy_version
) {
184 // Account for the length of the header block field.
185 size_t max_bytes_for_headers
=
186 kMaximumFieldLength
- LengthFieldSizeForVersion(spdy_version
);
188 // A minimal size header is twice the length field size (and has a
189 // zero-lengthed key and a zero-lengthed value).
190 return max_bytes_for_headers
/ (2 * LengthFieldSizeForVersion(spdy_version
));