| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "net/spdy/spdy_headers_block_parser.h" | |
| 6 | |
| 7 #include "base/sys_byteorder.h" | |
| 8 | |
| 9 namespace net { | |
| 10 namespace { | |
| 11 | |
| 12 // 0 is invalid according to both the SPDY 3.1 and HTTP/2 specifications. | |
| 13 const SpdyStreamId kInvalidStreamId = 0; | |
| 14 | |
| 15 } // anonymous namespace | |
| 16 | |
| 17 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024; | |
| 18 | |
| 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), | |
| 27 handler_(handler), | |
| 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); | |
| 33 } | |
| 34 | |
| 35 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {} | |
| 36 | |
| 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; | |
| 43 } | |
| 44 if (error_ != NO_PARSER_ERROR) { | |
| 45 LOG(DFATAL) << "Unexpected error: " << error_; | |
| 46 return false; | |
| 47 } | |
| 48 | |
| 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; | |
| 53 } | |
| 54 if (stream_id != stream_id_) { | |
| 55 LOG(DFATAL) << "Unexpected stream id: " << stream_id << " (expected " | |
| 56 << stream_id_ << ")"; | |
| 57 error_ = UNEXPECTED_STREAM_ID; | |
| 58 return false; | |
| 59 } | |
| 60 if (stream_id_ == kInvalidStreamId) { | |
| 61 LOG(DFATAL) << "Expected nonzero stream id, saw: " << stream_id_; | |
| 62 error_ = UNEXPECTED_STREAM_ID; | |
| 63 return false; | |
| 64 } | |
| 65 total_bytes_received_ += headers_data_length; | |
| 66 | |
| 67 SpdyPinnableBufferPiece prefix, key, value; | |
| 68 // Simultaneously tie lifetimes to the stack, and clear member variables. | |
| 69 prefix.Swap(&headers_block_prefix_); | |
| 70 key.Swap(&key_); | |
| 71 | |
| 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); | |
| 78 | |
| 79 switch (state_) { | |
| 80 case READING_HEADER_BLOCK_LEN: | |
| 81 next_state = READING_KEY_LEN; | |
| 82 ParseBlockLength(&reader); | |
| 83 break; | |
| 84 case READING_KEY_LEN: | |
| 85 next_state = READING_KEY; | |
| 86 ParseFieldLength(&reader); | |
| 87 break; | |
| 88 case READING_KEY: | |
| 89 next_state = READING_VALUE_LEN; | |
| 90 if (!reader.ReadN(next_field_length_, &key)) { | |
| 91 error_ = NEED_MORE_DATA; | |
| 92 } | |
| 93 break; | |
| 94 case READING_VALUE_LEN: | |
| 95 next_state = READING_VALUE; | |
| 96 ParseFieldLength(&reader); | |
| 97 break; | |
| 98 case READING_VALUE: | |
| 99 next_state = FINISHED_HEADER; | |
| 100 if (!reader.ReadN(next_field_length_, &value)) { | |
| 101 error_ = NEED_MORE_DATA; | |
| 102 } else { | |
| 103 handler_->OnHeader(key, value); | |
| 104 } | |
| 105 break; | |
| 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; | |
| 110 } else { | |
| 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; | |
| 117 } | |
| 118 } | |
| 119 break; | |
| 120 } | |
| 121 | |
| 122 if (error_ == NO_PARSER_ERROR) { | |
| 123 state_ = next_state; | |
| 124 | |
| 125 if (next_state == READING_HEADER_BLOCK_LEN) { | |
| 126 // We completed reading a full header block. Return to caller. | |
| 127 total_bytes_received_ = 0; | |
| 128 break; | |
| 129 } | |
| 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) { | |
| 134 key_.Swap(&key); | |
| 135 key_.Pin(); | |
| 136 } | |
| 137 reader.ReadN(reader.Available(), &headers_block_prefix_); | |
| 138 headers_block_prefix_.Pin(); | |
| 139 } | |
| 140 } | |
| 141 return error_ == NO_PARSER_ERROR; | |
| 142 } | |
| 143 | |
| 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; | |
| 149 } | |
| 150 if (error_ == NO_PARSER_ERROR) { | |
| 151 handler_->OnHeaderBlock(remaining_key_value_pairs_for_frame_); | |
| 152 } | |
| 153 } | |
| 154 | |
| 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; | |
| 159 } | |
| 160 } | |
| 161 | |
| 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; | |
| 167 return; | |
| 168 } | |
| 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)); | |
| 172 } else { | |
| 173 *parsed_length = ntohs(*reinterpret_cast<const uint16_t *>(buffer)); | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion( | |
| 178 SpdyMajorVersion spdy_version) { | |
| 179 if (spdy_version < SPDY3) { | |
| 180 return sizeof(uint16_t); | |
| 181 } | |
| 182 return sizeof(uint32_t); | |
| 183 } | |
| 184 | |
| 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); | |
| 190 | |
| 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)); | |
| 194 } | |
| 195 | |
| 196 } // namespace net | |
| OLD | NEW |