rAc - revert invalid suggestions to edit mode
[chromium-blink-merge.git] / net / spdy / spdy_headers_block_parser.cc
blob4ba6374a059a488731f58a6b8e50ff653ebeab86
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 <memory>
9 #include "base/sys_byteorder.h"
11 namespace net {
13 SpdyHeadersBlockParserReader::SpdyHeadersBlockParserReader(
14 base::StringPiece prefix,
15 base::StringPiece suffix)
16 : prefix_(prefix),
17 suffix_(suffix),
18 in_suffix_(false),
19 offset_(0) {}
21 size_t SpdyHeadersBlockParserReader::Available() {
22 if (in_suffix_) {
23 return suffix_.length() - offset_;
24 } else {
25 return prefix_.length() + suffix_.length() - offset_;
29 bool SpdyHeadersBlockParserReader::ReadN(size_t count, char* out) {
30 if (Available() < count)
31 return false;
33 if (!in_suffix_ && count > (prefix_.length() - offset_)) {
34 count -= prefix_.length() - offset_;
35 out = std::copy(prefix_.begin() + offset_, prefix_.end(), out);
36 in_suffix_ = true;
37 offset_ = 0;
38 // Fallthrough to suffix read.
39 } else if (!in_suffix_) {
40 // Read is satisfied by the prefix.
41 DCHECK_GE(prefix_.length() - offset_, count);
42 std::copy(prefix_.begin() + offset_,
43 prefix_.begin() + offset_ + count,
44 out);
45 offset_ += count;
46 return true;
48 // Read is satisfied by the suffix.
49 DCHECK(in_suffix_);
50 DCHECK_GE(suffix_.length() - offset_, count);
51 std::copy(suffix_.begin() + offset_,
52 suffix_.begin() + offset_ + count,
53 out);
54 offset_ += count;
55 return true;
58 std::vector<char> SpdyHeadersBlockParserReader::Remainder() {
59 std::vector<char> remainder(Available(), '\0');
60 if (remainder.size()) {
61 ReadN(remainder.size(), &remainder[0]);
63 DCHECK_EQ(0u, Available());
64 return remainder;
67 SpdyHeadersBlockParser::SpdyHeadersBlockParser(
68 SpdyHeadersHandlerInterface* handler) : state_(READING_HEADER_BLOCK_LEN),
69 remaining_key_value_pairs_for_frame_(0), next_field_len_(0),
70 handler_(handler) {
73 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {}
75 bool SpdyHeadersBlockParser::ParseUInt32(Reader* reader,
76 uint32_t* parsed_value) {
77 // Are there enough bytes available?
78 if (reader->Available() < sizeof(uint32_t)) {
79 return false;
82 // Read the required bytes, convert from network to host
83 // order and return the parsed out integer.
84 char buf[sizeof(uint32_t)];
85 reader->ReadN(sizeof(uint32_t), buf);
86 *parsed_value = base::NetToHost32(*reinterpret_cast<const uint32_t *>(buf));
87 return true;
90 void SpdyHeadersBlockParser::Reset() {
91 // Clear any saved state about the last headers block.
92 headers_block_prefix_.clear();
93 state_ = READING_HEADER_BLOCK_LEN;
96 void SpdyHeadersBlockParser::HandleControlFrameHeadersData(
97 const char* headers_data, size_t len) {
98 // Only do something if we received anything new.
99 if (len == 0) {
100 return;
103 // Reader avoids copying data.
104 base::StringPiece prefix;
105 if (headers_block_prefix_.size()) {
106 prefix.set(&headers_block_prefix_[0], headers_block_prefix_.size());
108 Reader reader(prefix, base::StringPiece(headers_data, len));
110 // If we didn't parse out yet the number of key-value pairs in this
111 // headers block, try to do it now (succeeds if we received enough bytes).
112 if (state_ == READING_HEADER_BLOCK_LEN) {
113 if (ParseUInt32(&reader, &remaining_key_value_pairs_for_frame_)) {
114 handler_->OnHeaderBlock(remaining_key_value_pairs_for_frame_);
115 state_ = READING_KEY_LEN;
116 } else {
117 headers_block_prefix_ = reader.Remainder();
118 return;
122 // Parse out and handle the key-value pairs.
123 while (remaining_key_value_pairs_for_frame_ > 0) {
124 // Parse the key-value length, in case we don't already have it.
125 if ((state_ == READING_KEY_LEN) || (state_ == READING_VALUE_LEN)) {
126 if (ParseUInt32(&reader, &next_field_len_)) {
127 state_ == READING_KEY_LEN ? state_ = READING_KEY :
128 state_ = READING_VALUE;
129 } else {
130 // Did not receive enough bytes.
131 break;
135 // Parse the next field if we received enough bytes.
136 if (reader.Available() >= next_field_len_) {
137 // Copy the field from the cord.
138 char* key_value_buf(new char[next_field_len_]);
139 reader.ReadN(next_field_len_, key_value_buf);
141 // Is this field a key?
142 if (state_ == READING_KEY) {
143 current_key.reset(key_value_buf);
144 key_len_ = next_field_len_;
145 state_ = READING_VALUE_LEN;
147 } else if (state_ == READING_VALUE) {
148 // We already had the key, now we got its value.
149 current_value.reset(key_value_buf);
151 // Call the handler for the key-value pair that we received.
152 handler_->OnKeyValuePair(
153 base::StringPiece(current_key.get(), key_len_),
154 base::StringPiece(current_value.get(), next_field_len_));
156 // Free allocated key and value strings.
157 current_key.reset();
158 current_value.reset();
160 // Finished handling a key-value pair.
161 remaining_key_value_pairs_for_frame_--;
163 // Finished handling a header, prepare for the next one.
164 state_ = READING_KEY_LEN;
166 } else {
167 // Did not receive enough bytes.
168 break;
172 // Unread suffix becomes the prefix upon next invocation.
173 headers_block_prefix_ = reader.Remainder();
175 // Did we finish handling the current block?
176 if (remaining_key_value_pairs_for_frame_ == 0) {
177 handler_->OnHeaderBlockEnd();
178 Reset();
182 } // namespace net