Home | History | Annotate | Download | only in spdy
      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