Cast: Fix rtcp event dedup logic in rtcp_receiver.
[chromium-blink-merge.git] / net / spdy / spdy_headers_block_parser.cc
blobeab55d2ad298960745afb5061c973c23f9911384
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"
9 namespace net {
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),
20 handler_(handler),
21 error_(OK) {
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) {
33 error_ = OK;
35 CHECK_EQ(error_, OK);
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_);
47 key.Swap(&key_);
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);
56 switch (state_) {
57 case READING_HEADER_BLOCK_LEN:
58 next_state = READING_KEY_LEN;
59 ParseBlockLength(&reader);
60 break;
61 case READING_KEY_LEN:
62 next_state = READING_KEY;
63 ParseFieldLength(&reader);
64 break;
65 case READING_KEY:
66 next_state = READING_VALUE_LEN;
67 if (!reader.ReadN(next_field_length_, &key)) {
68 error_ = NEED_MORE_DATA;
70 break;
71 case READING_VALUE_LEN:
72 next_state = READING_VALUE;
73 ParseFieldLength(&reader);
74 break;
75 case READING_VALUE:
76 next_state = FINISHED_HEADER;
77 if (!reader.ReadN(next_field_length_, &value)) {
78 error_ = NEED_MORE_DATA;
79 } else {
80 handler_->OnHeader(stream_id, key, value);
82 break;
83 case FINISHED_HEADER:
84 // Prepare for next header or block.
85 if (--remaining_key_value_pairs_for_frame_ > 0) {
86 next_state = READING_KEY_LEN;
87 } else {
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;
95 break;
96 default:
97 CHECK(false) << "Not reached.";
100 if (error_ == OK) {
101 state_ = next_state;
103 if (next_state == READING_HEADER_BLOCK_LEN) {
104 // We completed reading a full header block. Return to caller.
105 break;
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) {
111 key_.Swap(&key);
112 key_.Pin();
114 reader.ReadN(reader.Available(), &headers_block_prefix_);
115 headers_block_prefix_.Pin();
118 return error_ == OK;
121 void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) {
122 ParseLength(reader, &remaining_key_value_pairs_for_frame_);
123 if (error_ == OK &&
124 remaining_key_value_pairs_for_frame_ > max_headers_in_block_) {
125 error_ = HEADER_BLOCK_TOO_LARGE;
127 if (error_ == OK) {
128 handler_->OnHeaderBlock(stream_id_, remaining_key_value_pairs_for_frame_);
132 void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) {
133 ParseLength(reader, &next_field_length_);
134 if (error_ == OK &&
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;
145 return;
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));
150 } else {
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;
162 key_.Swap(&empty);
164 error_ = OK;
165 state_ = READING_HEADER_BLOCK_LEN;
166 stream_id_ = 0;
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));
188 } // namespace net