This source file includes following definitions.
- error_
 
- HandleControlFrameHeadersData
 
- ParseBlockLength
 
- ParseFieldLength
 
- ParseLength
 
- Reset
 
- LengthFieldSizeForVersion
 
- MaxNumberOfHeadersForVersion
 
#include "net/spdy/spdy_headers_block_parser.h"
#include "base/sys_byteorder.h"
namespace net {
const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024;
SpdyHeadersBlockParser::SpdyHeadersBlockParser(
    SpdyMajorVersion spdy_version,
    SpdyHeadersHandlerInterface* handler) :
    state_(READING_HEADER_BLOCK_LEN),
    length_field_size_(LengthFieldSizeForVersion(spdy_version)),
    max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version)),
    remaining_key_value_pairs_for_frame_(0),
    handler_(handler),
    error_(OK) {
  
  DCHECK(handler_ != NULL);
}
SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {}
bool SpdyHeadersBlockParser::HandleControlFrameHeadersData(
    SpdyStreamId stream_id,
    const char* headers_data,
    size_t headers_data_length) {
  if (error_ == NEED_MORE_DATA) {
    error_ = OK;
  }
  CHECK_EQ(error_, OK);
  
  
  if (state_ == READING_HEADER_BLOCK_LEN) {
    stream_id_ = stream_id;
  }
  CHECK_EQ(stream_id_, stream_id);
  SpdyPinnableBufferPiece prefix, key, value;
  
  prefix.Swap(&headers_block_prefix_);
  key.Swap(&key_);
  
  
  Reader reader(prefix.buffer(), prefix.length(),
                headers_data, headers_data_length);
  while (error_ == OK) {
    ParserState next_state(FINISHED_HEADER);
    switch (state_) {
      case READING_HEADER_BLOCK_LEN:
        next_state = READING_KEY_LEN;
        ParseBlockLength(&reader);
        break;
      case READING_KEY_LEN:
        next_state = READING_KEY;
        ParseFieldLength(&reader);
        break;
      case READING_KEY:
        next_state = READING_VALUE_LEN;
        if (!reader.ReadN(next_field_length_, &key)) {
          error_ = NEED_MORE_DATA;
        }
        break;
      case READING_VALUE_LEN:
        next_state = READING_VALUE;
        ParseFieldLength(&reader);
        break;
      case READING_VALUE:
        next_state = FINISHED_HEADER;
        if (!reader.ReadN(next_field_length_, &value)) {
          error_ = NEED_MORE_DATA;
        } else {
          handler_->OnHeader(stream_id, key, value);
        }
        break;
      case FINISHED_HEADER:
        
        if (--remaining_key_value_pairs_for_frame_ > 0) {
          next_state = READING_KEY_LEN;
        } else {
          next_state = READING_HEADER_BLOCK_LEN;
          handler_->OnHeaderBlockEnd(stream_id);
          
          if (reader.Available() != 0) {
            error_ = TOO_MUCH_DATA;
          }
        }
        break;
      default:
        CHECK(false) << "Not reached.";
    }
    if (error_ == OK) {
      state_ = next_state;
      if (next_state == READING_HEADER_BLOCK_LEN) {
        
        break;
      }
    } else if (error_ == NEED_MORE_DATA) {
      
      
      if (state_ > READING_KEY) {
        key_.Swap(&key);
        key_.Pin();
      }
      reader.ReadN(reader.Available(), &headers_block_prefix_);
      headers_block_prefix_.Pin();
    }
  }
  return error_ == OK;
}
void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) {
  ParseLength(reader, &remaining_key_value_pairs_for_frame_);
  if (error_ == OK &&
    remaining_key_value_pairs_for_frame_ > max_headers_in_block_) {
    error_ = HEADER_BLOCK_TOO_LARGE;
  }
  if (error_ == OK) {
    handler_->OnHeaderBlock(stream_id_, remaining_key_value_pairs_for_frame_);
  }
}
void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) {
  ParseLength(reader, &next_field_length_);
  if (error_ == OK &&
      next_field_length_ > kMaximumFieldLength) {
    error_ = HEADER_FIELD_TOO_LARGE;
  }
}
void SpdyHeadersBlockParser::ParseLength(Reader* reader,
                                         uint32_t* parsed_length) {
  char buffer[] = {0, 0, 0, 0};
  if (!reader->ReadN(length_field_size_, buffer)) {
    error_ = NEED_MORE_DATA;
    return;
  }
  
  if (length_field_size_ == sizeof(uint32_t)) {
    *parsed_length = ntohl(*reinterpret_cast<const uint32_t *>(buffer));
  } else {
    *parsed_length = ntohs(*reinterpret_cast<const uint16_t *>(buffer));
  }
}
void SpdyHeadersBlockParser::Reset() {
  {
    SpdyPinnableBufferPiece empty;
    headers_block_prefix_.Swap(&empty);
  }
  {
    SpdyPinnableBufferPiece empty;
    key_.Swap(&empty);
  }
  error_ = OK;
  state_ = READING_HEADER_BLOCK_LEN;
  stream_id_ = 0;
}
size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion(
    SpdyMajorVersion spdy_version) {
  if (spdy_version < SPDY3) {
    return sizeof(uint16_t);
  }
  return sizeof(uint32_t);
}
size_t SpdyHeadersBlockParser::MaxNumberOfHeadersForVersion(
    SpdyMajorVersion spdy_version) {
  
  size_t max_bytes_for_headers =
      kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version);
  
  
  return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version));
}
}