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 11 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024; 12 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), 21 handler_(handler), 22 error_(OK) { 23 // The handler that we set must not be NULL. 24 DCHECK(handler_ != NULL); 25 } 26 27 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {} 28 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) { 34 error_ = OK; 35 } 36 CHECK_EQ(error_, OK); 37 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; 42 } 43 CHECK_EQ(stream_id_, stream_id); 44 45 total_bytes_received_ += headers_data_length; 46 47 SpdyPinnableBufferPiece prefix, key, value; 48 // Simultaneously tie lifetimes to the stack, and clear member variables. 49 prefix.Swap(&headers_block_prefix_); 50 key.Swap(&key_); 51 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); 58 59 switch (state_) { 60 case READING_HEADER_BLOCK_LEN: 61 next_state = READING_KEY_LEN; 62 ParseBlockLength(&reader); 63 break; 64 case READING_KEY_LEN: 65 next_state = READING_KEY; 66 ParseFieldLength(&reader); 67 break; 68 case READING_KEY: 69 next_state = READING_VALUE_LEN; 70 if (!reader.ReadN(next_field_length_, &key)) { 71 error_ = NEED_MORE_DATA; 72 } 73 break; 74 case READING_VALUE_LEN: 75 next_state = READING_VALUE; 76 ParseFieldLength(&reader); 77 break; 78 case READING_VALUE: 79 next_state = FINISHED_HEADER; 80 if (!reader.ReadN(next_field_length_, &value)) { 81 error_ = NEED_MORE_DATA; 82 } else { 83 handler_->OnHeader(stream_id, key, value); 84 } 85 break; 86 case FINISHED_HEADER: 87 // Prepare for next header or block. 88 if (--remaining_key_value_pairs_for_frame_ > 0) { 89 next_state = READING_KEY_LEN; 90 } else { 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; 96 } 97 } 98 break; 99 default: 100 CHECK(false) << "Not reached."; 101 } 102 103 if (error_ == OK) { 104 state_ = next_state; 105 106 if (next_state == READING_HEADER_BLOCK_LEN) { 107 // We completed reading a full header block. Return to caller. 108 total_bytes_received_ = 0; 109 break; 110 } 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) { 115 key_.Swap(&key); 116 key_.Pin(); 117 } 118 reader.ReadN(reader.Available(), &headers_block_prefix_); 119 headers_block_prefix_.Pin(); 120 } 121 } 122 return error_ == OK; 123 } 124 125 void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) { 126 ParseLength(reader, &remaining_key_value_pairs_for_frame_); 127 if (error_ == OK && 128 remaining_key_value_pairs_for_frame_ > max_headers_in_block_) { 129 error_ = HEADER_BLOCK_TOO_LARGE; 130 } 131 if (error_ == OK) { 132 handler_->OnHeaderBlock(stream_id_, remaining_key_value_pairs_for_frame_); 133 } 134 } 135 136 void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) { 137 ParseLength(reader, &next_field_length_); 138 if (error_ == OK && 139 next_field_length_ > kMaximumFieldLength) { 140 error_ = HEADER_FIELD_TOO_LARGE; 141 } 142 } 143 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; 149 return; 150 } 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)); 154 } else { 155 *parsed_length = ntohs(*reinterpret_cast<const uint16_t *>(buffer)); 156 } 157 } 158 159 void SpdyHeadersBlockParser::Reset() { 160 { 161 SpdyPinnableBufferPiece empty; 162 headers_block_prefix_.Swap(&empty); 163 } 164 { 165 SpdyPinnableBufferPiece empty; 166 key_.Swap(&empty); 167 } 168 error_ = OK; 169 state_ = READING_HEADER_BLOCK_LEN; 170 stream_id_ = 0; 171 total_bytes_received_ = 0; 172 } 173 174 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion( 175 SpdyMajorVersion spdy_version) { 176 if (spdy_version < SPDY3) { 177 return sizeof(uint16_t); 178 } 179 return sizeof(uint32_t); 180 } 181 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); 187 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)); 191 } 192 193 } // namespace net 194