// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(rtenhove) clean up frame buffer size calculations so that we aren't
// constantly adding and subtracting header sizes; this is ugly and error-
// prone.

#include "net/spdy/spdy_framer.h"

#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/stats_counters.h"
#include "base/third_party/valgrind/memcheck.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_frame_reader.h"
#include "net/spdy/spdy_bitmasks.h"
#include "third_party/zlib/zlib.h"

using std::vector;

namespace net {

namespace {

// Compute the id of our dictionary so that we know we're using the
// right one when asked for it.
uLong CalculateDictionaryId(const char* dictionary,
                            const size_t dictionary_size) {
  uLong initial_value = adler32(0L, Z_NULL, 0);
  return adler32(initial_value,
                 reinterpret_cast<const Bytef*>(dictionary),
                 dictionary_size);
}

struct DictionaryIds {
  DictionaryIds()
    : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
      v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
  {}
  const uLong v2_dictionary_id;
  const uLong v3_dictionary_id;
};

// Adler ID for the SPDY header compressor dictionaries. Note that they are
// initialized lazily to avoid static initializers.
base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;

// Used to indicate no flags in a SPDY flags field.
const uint8 kNoFlags = 0;

}  // namespace

const SpdyStreamId SpdyFramer::kInvalidStream = -1;
const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
// The size of the control frame buffer. Must be >= the minimum size of the
// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
// calculation details.
const size_t SpdyFramer::kControlFrameBufferSize = 18;

#ifdef DEBUG_SPDY_STATE_CHANGES
#define CHANGE_STATE(newstate)                                  \
  do {                                                          \
    DVLOG(1) << "Changing state from: "                         \
             << StateToString(state_)                           \
             << " to " << StateToString(newstate) << "\n";      \
    DCHECK(state_ != SPDY_ERROR);                               \
    DCHECK_EQ(previous_state_, state_);                         \
    previous_state_ = state_;                                   \
    state_ = newstate;                                          \
  } while (false)
#else
#define CHANGE_STATE(newstate)                                  \
  do {                                                          \
    DCHECK(state_ != SPDY_ERROR);                               \
    DCHECK_EQ(previous_state_, state_);                         \
    previous_state_ = state_;                                   \
    state_ = newstate;                                          \
  } while (false)
#endif

SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version,
                                                      uint32 wire) {
  if (version < 3) {
    ConvertFlagsAndIdForSpdy2(&wire);
  }
  return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
}

SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
    : flags_(flags), id_(id & 0x00ffffff) {
  DCHECK_GT(1u << 24, id) << "SPDY setting ID too large.";
}

uint32 SettingsFlagsAndId::GetWireFormat(int version) const {
  uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
  if (version < 3) {
    ConvertFlagsAndIdForSpdy2(&wire);
  }
  return wire;
}

// SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
// This method is used to preserve buggy behavior and works on both
// little-endian and big-endian hosts.
// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
// as well as vice versa).
void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
    uint8* wire_array = reinterpret_cast<uint8*>(val);
    std::swap(wire_array[0], wire_array[3]);
    std::swap(wire_array[1], wire_array[2]);
}

SpdyCredential::SpdyCredential() : slot(0) {}
SpdyCredential::~SpdyCredential() {}

SpdyFramer::SpdyFramer(SpdyMajorVersion version)
    : current_frame_buffer_(new char[kControlFrameBufferSize]),
      enable_compression_(true),
      visitor_(NULL),
      debug_visitor_(NULL),
      display_protocol_("SPDY"),
      spdy_version_(version),
      syn_frame_processed_(false),
      probable_http_response_(false) {
  DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
  DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
  Reset();
}

SpdyFramer::~SpdyFramer() {
  if (header_compressor_.get()) {
    deflateEnd(header_compressor_.get());
  }
  if (header_decompressor_.get()) {
    inflateEnd(header_decompressor_.get());
  }
}

void SpdyFramer::Reset() {
  state_ = SPDY_RESET;
  previous_state_ = SPDY_RESET;
  error_code_ = SPDY_NO_ERROR;
  remaining_data_length_ = 0;
  remaining_control_header_ = 0;
  current_frame_buffer_length_ = 0;
  current_frame_type_ = DATA;
  current_frame_flags_ = 0;
  current_frame_length_ = 0;
  current_frame_stream_id_ = kInvalidStream;
  settings_scratch_.Reset();
}

size_t SpdyFramer::GetDataFrameMinimumSize() const {
  // Size, in bytes, of the data frame header. Future versions of SPDY
  // will likely vary this, so we allow for the flexibility of a function call
  // for this value as opposed to a constant.
  return 8;
}

// Size, in bytes, of the control frame header.
size_t SpdyFramer::GetControlFrameHeaderSize() const {
  switch (protocol_version()) {
    case SPDY2:
    case SPDY3:
    case SPDY4:
      return 8;
  }
  LOG(DFATAL) << "Unhandled SPDY version.";
  return 0;
}

size_t SpdyFramer::GetSynStreamMinimumSize() const {
  // Size, in bytes, of a SYN_STREAM frame not including the variable-length
  // name-value block.
  if (spdy_version_ < 4) {
    // Calculated as:
    // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot)
    return GetControlFrameHeaderSize() + 10;
  } else {
    // Calculated as:
    // frame prefix + 4 (associated stream ID) + 1 (priority) + 1 (slot)
    return GetControlFrameHeaderSize() + 6;
  }
}

size_t SpdyFramer::GetSynReplyMinimumSize() const {
  // Size, in bytes, of a SYN_REPLY frame not including the variable-length
  // name-value block.
  size_t size = GetControlFrameHeaderSize();
  if (spdy_version_ < 4) {
    // Calculated as:
    // control frame header + 4 (stream IDs)
    size += 4;
  }

  // In SPDY 2, there were 2 unused bytes before payload.
  if (protocol_version() < 3) {
    size += 2;
  }

  return size;
}

size_t SpdyFramer::GetRstStreamSize() const {
  // Size, in bytes, of a RST_STREAM frame.
  if (spdy_version_ < 4) {
    // Calculated as:
    // control frame header + 4 (stream id) + 4 (status code)
    return GetControlFrameHeaderSize() + 8;
  } else {
    // Calculated as:
    // frame prefix + 4 (status code)
    return GetControlFrameHeaderSize() + 4;
  }
}

size_t SpdyFramer::GetSettingsMinimumSize() const {
  // Size, in bytes, of a SETTINGS frame not including the IDs and values
  // from the variable-length value block. Calculated as:
  // control frame header + 4 (number of ID/value pairs)
  return GetControlFrameHeaderSize() + 4;
}

size_t SpdyFramer::GetPingSize() const {
  // Size, in bytes, of this PING frame. Calculated as:
  // control frame header + 4 (id)
  return GetControlFrameHeaderSize() + 4;
}

size_t SpdyFramer::GetGoAwaySize() const {
  // Size, in bytes, of this GOAWAY frame. Calculated as:
  // control frame header + 4 (last good stream id)
  size_t size = GetControlFrameHeaderSize() + 4;

  // SPDY 3+ GOAWAY frames also contain a status.
  if (protocol_version() >= 3) {
    size += 4;
  }

  return size;
}

size_t SpdyFramer::GetHeadersMinimumSize() const  {
  // Size, in bytes, of a HEADERS frame not including the variable-length
  // name-value block.
  size_t size = GetControlFrameHeaderSize();
  if (spdy_version_ < 4) {
    // Calculated as:
    // control frame header + 4 (stream IDs)
    size += 4;
  }

  // In SPDY 2, there were 2 unused bytes before payload.
  if (protocol_version() < 3) {
    size += 2;
  }

  return size;
}

size_t SpdyFramer::GetWindowUpdateSize() const {
  // Size, in bytes, of a WINDOW_UPDATE frame.
  if (spdy_version_ < 4) {
    // Calculated as:
    // control frame header + 4 (stream id) + 4 (delta)
    return GetControlFrameHeaderSize() + 8;
  } else {
    // Calculated as:
    // frame prefix + 4 (delta)
    return GetControlFrameHeaderSize() + 4;
  }
}

size_t SpdyFramer::GetCredentialMinimumSize() const {
  // Size, in bytes, of a CREDENTIAL frame sans variable-length certificate list
  // and proof. Calculated as:
  // control frame header + 2 (slot)
  return GetControlFrameHeaderSize() + 2;
}

size_t SpdyFramer::GetBlockedSize() const {
  DCHECK_LE(4, protocol_version());
  // Size, in bytes, of a BLOCKED frame.
  // The BLOCKED frame has no payload beyond the control frame header.
  return GetControlFrameHeaderSize();
}

size_t SpdyFramer::GetPushPromiseMinimumSize() const {
  DCHECK_LE(4, protocol_version());
  // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
  // Calculated as frame prefix + 4 (promised stream id).
  return GetControlFrameHeaderSize() + 4;
}

size_t SpdyFramer::GetFrameMinimumSize() const {
  return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
}

size_t SpdyFramer::GetFrameMaximumSize() const {
  return (protocol_version() < 4) ? 0xffffff : 0xffff;
}

size_t SpdyFramer::GetDataFrameMaximumPayload() const {
  return GetFrameMaximumSize() - GetDataFrameMinimumSize();
}

const char* SpdyFramer::StateToString(int state) {
  switch (state) {
    case SPDY_ERROR:
      return "ERROR";
    case SPDY_AUTO_RESET:
      return "AUTO_RESET";
    case SPDY_RESET:
      return "RESET";
    case SPDY_READING_COMMON_HEADER:
      return "READING_COMMON_HEADER";
    case SPDY_CONTROL_FRAME_PAYLOAD:
      return "CONTROL_FRAME_PAYLOAD";
    case SPDY_IGNORE_REMAINING_PAYLOAD:
      return "IGNORE_REMAINING_PAYLOAD";
    case SPDY_FORWARD_STREAM_FRAME:
      return "FORWARD_STREAM_FRAME";
    case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
      return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
    case SPDY_CONTROL_FRAME_HEADER_BLOCK:
      return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
    case SPDY_CREDENTIAL_FRAME_PAYLOAD:
      return "SPDY_CREDENTIAL_FRAME_PAYLOAD";
    case SPDY_SETTINGS_FRAME_PAYLOAD:
      return "SPDY_SETTINGS_FRAME_PAYLOAD";
  }
  return "UNKNOWN_STATE";
}

void SpdyFramer::set_error(SpdyError error) {
  DCHECK(visitor_);
  error_code_ = error;
  CHANGE_STATE(SPDY_ERROR);
  visitor_->OnError(this);
}

const char* SpdyFramer::ErrorCodeToString(int error_code) {
  switch (error_code) {
    case SPDY_NO_ERROR:
      return "NO_ERROR";
    case SPDY_INVALID_CONTROL_FRAME:
      return "INVALID_CONTROL_FRAME";
    case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
      return "CONTROL_PAYLOAD_TOO_LARGE";
    case SPDY_ZLIB_INIT_FAILURE:
      return "ZLIB_INIT_FAILURE";
    case SPDY_UNSUPPORTED_VERSION:
      return "UNSUPPORTED_VERSION";
    case SPDY_DECOMPRESS_FAILURE:
      return "DECOMPRESS_FAILURE";
    case SPDY_COMPRESS_FAILURE:
      return "COMPRESS_FAILURE";
    case SPDY_INVALID_DATA_FRAME_FLAGS:
      return "SPDY_INVALID_DATA_FRAME_FLAGS";
    case SPDY_INVALID_CONTROL_FRAME_FLAGS:
      return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
  }
  return "UNKNOWN_ERROR";
}

const char* SpdyFramer::StatusCodeToString(int status_code) {
  switch (status_code) {
    case RST_STREAM_INVALID:
      return "INVALID";
    case RST_STREAM_PROTOCOL_ERROR:
      return "PROTOCOL_ERROR";
    case RST_STREAM_INVALID_STREAM:
      return "INVALID_STREAM";
    case RST_STREAM_REFUSED_STREAM:
      return "REFUSED_STREAM";
    case RST_STREAM_UNSUPPORTED_VERSION:
      return "UNSUPPORTED_VERSION";
    case RST_STREAM_CANCEL:
      return "CANCEL";
    case RST_STREAM_INTERNAL_ERROR:
      return "INTERNAL_ERROR";
    case RST_STREAM_FLOW_CONTROL_ERROR:
      return "FLOW_CONTROL_ERROR";
    case RST_STREAM_STREAM_IN_USE:
      return "STREAM_IN_USE";
    case RST_STREAM_STREAM_ALREADY_CLOSED:
      return "STREAM_ALREADY_CLOSED";
    case RST_STREAM_INVALID_CREDENTIALS:
      return "INVALID_CREDENTIALS";
    case RST_STREAM_FRAME_TOO_LARGE:
      return "FRAME_TOO_LARGE";
  }
  return "UNKNOWN_STATUS";
}

const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
  switch (type) {
    case DATA:
      return "DATA";
    case SYN_STREAM:
      return "SYN_STREAM";
    case SYN_REPLY:
      return "SYN_REPLY";
    case RST_STREAM:
      return "RST_STREAM";
    case SETTINGS:
      return "SETTINGS";
    case NOOP:
      return "NOOP";
    case PING:
      return "PING";
    case GOAWAY:
      return "GOAWAY";
    case HEADERS:
      return "HEADERS";
    case WINDOW_UPDATE:
      return "WINDOW_UPDATE";
    case CREDENTIAL:
      return "CREDENTIAL";
    case BLOCKED:
      return "BLOCKED";
    case PUSH_PROMISE:
      return "PUSH_PROMISE";
  }
  return "UNKNOWN_CONTROL_TYPE";
}

size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
  DCHECK(visitor_);
  DCHECK(data);

  size_t original_len = len;
  do {
    previous_state_ = state_;
    switch (state_) {
      case SPDY_ERROR:
        goto bottom;

      case SPDY_AUTO_RESET:
      case SPDY_RESET:
        Reset();
        if (len > 0) {
          CHANGE_STATE(SPDY_READING_COMMON_HEADER);
        }
        break;

      case SPDY_READING_COMMON_HEADER: {
        size_t bytes_read = ProcessCommonHeader(data, len);
        len -= bytes_read;
        data += bytes_read;
        break;
      }

      case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
        // Control frames that contain header blocks
        // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE)
        // take a different path through the state machine - they
        // will go:
        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
        //   2. SPDY_CONTROL_FRAME_HEADER_BLOCK
        //
        // SETTINGS frames take a slightly modified route:
        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
        //   2. SPDY_SETTINGS_FRAME_PAYLOAD
        //
        //  All other control frames will use the alternate route directly to
        //  SPDY_CONTROL_FRAME_PAYLOAD
        int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
        len -= bytes_read;
        data += bytes_read;
        break;
      }

      case SPDY_SETTINGS_FRAME_PAYLOAD: {
        int bytes_read = ProcessSettingsFramePayload(data, len);
        len -= bytes_read;
        data += bytes_read;
        break;
      }

      case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
        int bytes_read = ProcessControlFrameHeaderBlock(data, len);
        len -= bytes_read;
        data += bytes_read;
        break;
      }

      case SPDY_CREDENTIAL_FRAME_PAYLOAD: {
        size_t bytes_read = ProcessCredentialFramePayload(data, len);
        len -= bytes_read;
        data += bytes_read;
        break;
      }

      case SPDY_CONTROL_FRAME_PAYLOAD: {
        size_t bytes_read = ProcessControlFramePayload(data, len);
        len -= bytes_read;
        data += bytes_read;
        break;
      }

      case SPDY_IGNORE_REMAINING_PAYLOAD:
        // control frame has too-large payload
        // intentional fallthrough
      case SPDY_FORWARD_STREAM_FRAME: {
        size_t bytes_read = ProcessDataFramePayload(data, len);
        len -= bytes_read;
        data += bytes_read;
        break;
      }
      default:
        LOG(DFATAL) << "Invalid value for " << display_protocol_
                    << " framer state: " << state_;
        // This ensures that we don't infinite-loop if state_ gets an
        // invalid value somehow, such as due to a SpdyFramer getting deleted
        // from a callback it calls.
        goto bottom;
    }
  } while (state_ != previous_state_);
 bottom:
  DCHECK(len == 0 || state_ == SPDY_ERROR);
  if (current_frame_buffer_length_ == 0 &&
      remaining_data_length_ == 0 &&
      remaining_control_header_ == 0) {
    DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
        << "State: " << StateToString(state_);
  }

  return original_len - len;
}

size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
  // This should only be called when we're in the SPDY_READING_COMMON_HEADER
  // state.
  DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);

  size_t original_len = len;

  // Update current frame buffer as needed.
  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
    size_t bytes_desired =
        GetControlFrameHeaderSize() - current_frame_buffer_length_;
    UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
  }

  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
    // Not enough information to do anything meaningful.
    return original_len - len;
  }

  // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
  // when processing DATA frames below.
  scoped_ptr<SpdyFrameReader> reader(
      new SpdyFrameReader(current_frame_buffer_.get(),
                          current_frame_buffer_length_));

  uint16 version = 0;
  bool is_control_frame = false;

  uint16 control_frame_type_field = DATA;
  // ProcessControlFrameHeader() will set current_frame_type_ to the
  // correct value if this is a valid control frame.
  current_frame_type_ = DATA;
  if (protocol_version() < 4) {
    bool successful_read = reader->ReadUInt16(&version);
    DCHECK(successful_read);
    is_control_frame = (version & kControlFlagMask) != 0;
    version &= ~kControlFlagMask;  // Only valid for control frames.

    if (is_control_frame) {
      // We check control_frame_type_field's validity in
      // ProcessControlFrameHeader().
      successful_read = reader->ReadUInt16(&control_frame_type_field);
    } else {
      reader->Rewind();
      successful_read = reader->ReadUInt31(&current_frame_stream_id_);
    }
    DCHECK(successful_read);

    successful_read = reader->ReadUInt8(&current_frame_flags_);
    DCHECK(successful_read);

    uint32 length_field = 0;
    successful_read = reader->ReadUInt24(&length_field);
    DCHECK(successful_read);
    remaining_data_length_ = length_field;
    current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
  } else {
    version = protocol_version();
    uint16 length_field = 0;
    bool successful_read = reader->ReadUInt16(&length_field);
    DCHECK(successful_read);
    current_frame_length_ = length_field;

    uint8 control_frame_type_field_uint8 = DATA;
    successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
    DCHECK(successful_read);
    // We check control_frame_type_field's validity in
    // ProcessControlFrameHeader().
    control_frame_type_field = control_frame_type_field_uint8;
    is_control_frame = (control_frame_type_field != DATA);

    successful_read = reader->ReadUInt8(&current_frame_flags_);
    DCHECK(successful_read);

    successful_read = reader->ReadUInt31(&current_frame_stream_id_);
    DCHECK(successful_read);

    remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
  }
  DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
                             : GetDataFrameMinimumSize(),
            reader->GetBytesConsumed());
  DCHECK_EQ(current_frame_length_,
            remaining_data_length_ + reader->GetBytesConsumed());

  // This is just a sanity check for help debugging early frame errors.
  if (remaining_data_length_ > 1000000u) {
    // The strncmp for 5 is safe because we only hit this point if we
    // have kMinCommonHeader (8) bytes
    if (!syn_frame_processed_ &&
        strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
      LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
                   << " request";
      probable_http_response_ = true;
    } else {
      LOG(WARNING) << "Unexpectedly large frame.  " << display_protocol_
                   << " session is likely corrupt.";
    }
  }

  // if we're here, then we have the common header all received.
  if (!is_control_frame) {
    if (current_frame_flags_ & ~DATA_FLAG_FIN) {
      set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
    } else {
      visitor_->OnDataFrameHeader(current_frame_stream_id_,
                                  remaining_data_length_,
                                  current_frame_flags_ & DATA_FLAG_FIN);
      if (remaining_data_length_ > 0) {
        CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
      } else {
        // Empty data frame.
        if (current_frame_flags_ & DATA_FLAG_FIN) {
          visitor_->OnStreamFrameData(
              current_frame_stream_id_, NULL, 0, true);
        }
        CHANGE_STATE(SPDY_AUTO_RESET);
      }
    }
  } else if (version != spdy_version_) {
    // We check version before we check validity: version can never be
    // 'invalid', it can only be unsupported.
    DVLOG(1) << "Unsupported SPDY version " << version
             << " (expected " << spdy_version_ << ")";
    set_error(SPDY_UNSUPPORTED_VERSION);
  } else {
    ProcessControlFrameHeader(control_frame_type_field);
  }

  return original_len - len;
}

void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
  DCHECK_EQ(SPDY_NO_ERROR, error_code_);
  DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);

  if (control_frame_type_field < FIRST_CONTROL_TYPE ||
      control_frame_type_field > LAST_CONTROL_TYPE) {
    set_error(SPDY_INVALID_CONTROL_FRAME);
    return;
  }

  current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);

  if (current_frame_type_ == NOOP) {
    DVLOG(1) << "NOOP control frame found. Ignoring.";
    CHANGE_STATE(SPDY_AUTO_RESET);
    return;
  }

  // Do some sanity checking on the control frame sizes and flags.
  switch (current_frame_type_) {
    case SYN_STREAM:
      if (current_frame_length_ < GetSynStreamMinimumSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ &
                 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case SYN_REPLY:
      if (current_frame_length_ < GetSynReplyMinimumSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case RST_STREAM:
      if (current_frame_length_ != GetRstStreamSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ != 0) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case SETTINGS:
      // Make sure that we have an integral number of 8-byte key/value pairs,
      // plus a 4-byte length field.
      if (current_frame_length_ < GetSettingsMinimumSize() ||
          (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) {
        DLOG(WARNING) << "Invalid length for SETTINGS frame: "
                      << current_frame_length_;
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ &
                 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case PING:
      if (current_frame_length_ != GetPingSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ != 0) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case GOAWAY:
      {
        if (current_frame_length_ != GetGoAwaySize()) {
          set_error(SPDY_INVALID_CONTROL_FRAME);
        } else if (current_frame_flags_ != 0) {
          set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
        }
        break;
      }
    case HEADERS:
      if (current_frame_length_ < GetHeadersMinimumSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case WINDOW_UPDATE:
      if (current_frame_length_ != GetWindowUpdateSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ != 0) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case CREDENTIAL:
      if (current_frame_length_ < GetCredentialMinimumSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ != 0) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case BLOCKED:
      if (current_frame_length_ != GetBlockedSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ != 0) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    case PUSH_PROMISE:
      if (current_frame_length_ < GetPushPromiseMinimumSize()) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
      } else if (current_frame_flags_ != 0) {
        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
      }
      break;
    default:
      LOG(WARNING) << "Valid " << display_protocol_
                   << " control frame with unhandled type: "
                   << current_frame_type_;
      // This branch should be unreachable because of the frame type bounds
      // check above. However, we DLOG(FATAL) here in an effort to painfully
      // club the head of the developer who failed to keep this file in sync
      // with spdy_protocol.h.
      DLOG(FATAL);
      set_error(SPDY_INVALID_CONTROL_FRAME);
      break;
  }

  if (state_ == SPDY_ERROR) {
    return;
  }

  if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
    DLOG(WARNING) << "Received control frame with way too big of a payload: "
                  << current_frame_length_;
    set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
    return;
  }

  if (current_frame_type_ == CREDENTIAL) {
    CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD);
    return;
  }

  // Determine the frame size without variable-length data.
  int32 frame_size_without_variable_data;
  switch (current_frame_type_) {
    case SYN_STREAM:
      syn_frame_processed_ = true;
      frame_size_without_variable_data = GetSynStreamMinimumSize();
      break;
    case SYN_REPLY:
      syn_frame_processed_ = true;
      frame_size_without_variable_data = GetSynReplyMinimumSize();
      break;
    case SETTINGS:
      frame_size_without_variable_data = GetSettingsMinimumSize();
      break;
    case HEADERS:
      frame_size_without_variable_data = GetHeadersMinimumSize();
      break;
    case PUSH_PROMISE:
      frame_size_without_variable_data = GetPushPromiseMinimumSize();
      break;
    default:
      frame_size_without_variable_data = -1;
      break;
  }

  if ((frame_size_without_variable_data == -1) &&
      (current_frame_length_ > kControlFrameBufferSize)) {
    // We should already be in an error state. Double-check.
    DCHECK_EQ(SPDY_ERROR, state_);
    if (state_ != SPDY_ERROR) {
      LOG(DFATAL) << display_protocol_
                  << " control frame buffer too small for fixed-length frame.";
      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
    }
    return;
  }

  if (frame_size_without_variable_data > 0) {
    // We have a control frame with a header block. We need to parse the
    // remainder of the control frame's header before we can parse the header
    // block. The start of the header block varies with the control type.
    DCHECK_GE(frame_size_without_variable_data,
              static_cast<int32>(current_frame_buffer_length_));
    remaining_control_header_ = frame_size_without_variable_data -
        current_frame_buffer_length_;

    CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
    return;
  }

  CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
}

size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
                                            size_t max_bytes) {
  size_t bytes_to_read = std::min(*len, max_bytes);
  if (bytes_to_read > 0) {
    DCHECK_GE(kControlFrameBufferSize,
              current_frame_buffer_length_ + bytes_to_read);
    memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
           *data,
           bytes_to_read);
    current_frame_buffer_length_ += bytes_to_read;
    *data += bytes_to_read;
    *len -= bytes_to_read;
  }
  return bytes_to_read;
}

size_t SpdyFramer::GetSerializedLength(const int spdy_version,
                                       const SpdyHeaderBlock* headers) {
  const size_t num_name_value_pairs_size
      = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32);
  const size_t length_of_name_size = num_name_value_pairs_size;
  const size_t length_of_value_size = num_name_value_pairs_size;

  size_t total_length = num_name_value_pairs_size;
  for (SpdyHeaderBlock::const_iterator it = headers->begin();
       it != headers->end();
       ++it) {
    // We add space for the length of the name and the length of the value as
    // well as the length of the name and the length of the value.
    total_length += length_of_name_size + it->first.size() +
                    length_of_value_size + it->second.size();
  }
  return total_length;
}

void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
                                  const int spdy_version,
                                  const SpdyHeaderBlock* headers) {
  if (spdy_version < 3) {
    frame->WriteUInt16(headers->size());  // Number of headers.
  } else {
    frame->WriteUInt32(headers->size());  // Number of headers.
  }
  SpdyHeaderBlock::const_iterator it;
  for (it = headers->begin(); it != headers->end(); ++it) {
    if (spdy_version < 3) {
      frame->WriteString(it->first);
      frame->WriteString(it->second);
    } else {
      frame->WriteStringPiece32(it->first);
      frame->WriteStringPiece32(it->second);
    }
  }
}

// TODO(phajdan.jr): Clean up after we no longer need
// to workaround http://crbug.com/139744.
#if !defined(USE_SYSTEM_ZLIB)

// These constants are used by zlib to differentiate between normal data and
// cookie data. Cookie data is handled specially by zlib when compressing.
enum ZDataClass {
  // kZStandardData is compressed normally, save that it will never match
  // against any other class of data in the window.
  kZStandardData = Z_CLASS_STANDARD,
  // kZCookieData is compressed in its own Huffman blocks and only matches in
  // its entirety and only against other kZCookieData blocks. Any matches must
  // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
  // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
  // prefix matches.
  kZCookieData = Z_CLASS_COOKIE,
  // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
  // against the window.
  kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
};

// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
// needed when switching between classes of data.
static void WriteZ(const base::StringPiece& data,
                   ZDataClass clas,
                   z_stream* out) {
  int rv;

  // If we are switching from standard to non-standard data then we need to end
  // the current Huffman context to avoid it leaking between them.
  if (out->clas == kZStandardData &&
      clas != kZStandardData) {
    out->avail_in = 0;
    rv = deflate(out, Z_PARTIAL_FLUSH);
    DCHECK_EQ(Z_OK, rv);
    DCHECK_EQ(0u, out->avail_in);
    DCHECK_LT(0u, out->avail_out);
  }

  out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
  out->avail_in = data.size();
  out->clas = clas;
  if (clas == kZStandardData) {
    rv = deflate(out, Z_NO_FLUSH);
  } else {
    rv = deflate(out, Z_PARTIAL_FLUSH);
  }
  if (!data.empty()) {
    // If we didn't provide any data then zlib will return Z_BUF_ERROR.
    DCHECK_EQ(Z_OK, rv);
  }
  DCHECK_EQ(0u, out->avail_in);
  DCHECK_LT(0u, out->avail_out);
}

// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
static void WriteLengthZ(size_t n,
                         unsigned length,
                         ZDataClass clas,
                         z_stream* out) {
  char buf[4];
  DCHECK_LE(length, sizeof(buf));
  for (unsigned i = 1; i <= length; i++) {
    buf[length - i] = n;
    n >>= 8;
  }
  WriteZ(base::StringPiece(buf, length), clas, out);
}

// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
// manner that resists the length of the compressed data from compromising
// cookie data.
void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
                                     z_stream* z) const {
  unsigned length_length = 4;
  if (spdy_version_ < 3)
    length_length = 2;

  WriteLengthZ(headers->size(), length_length, kZStandardData, z);

  std::map<std::string, std::string>::const_iterator it;
  for (it = headers->begin(); it != headers->end(); ++it) {
    WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
    WriteZ(it->first, kZStandardData, z);

    if (it->first == "cookie") {
      // We require the cookie values (save for the last) to end with a
      // semicolon and (save for the first) to start with a space. This is
      // typically the format that we are given them in but we reserialize them
      // to be sure.

      std::vector<base::StringPiece> cookie_values;
      size_t cookie_length = 0;
      base::StringPiece cookie_data(it->second);

      for (;;) {
        while (!cookie_data.empty() &&
               (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
          cookie_data.remove_prefix(1);
        }
        if (cookie_data.empty())
          break;

        size_t i;
        for (i = 0; i < cookie_data.size(); i++) {
          if (cookie_data[i] == ';')
            break;
        }
        if (i < cookie_data.size()) {
          cookie_values.push_back(cookie_data.substr(0, i));
          cookie_length += i + 2 /* semicolon and space */;
          cookie_data.remove_prefix(i + 1);
        } else {
          cookie_values.push_back(cookie_data);
          cookie_length += cookie_data.size();
          cookie_data.remove_prefix(i);
        }
      }

      WriteLengthZ(cookie_length, length_length, kZStandardData, z);
      for (size_t i = 0; i < cookie_values.size(); i++) {
        std::string cookie;
        // Since zlib will only back-reference complete cookies, a cookie that
        // is currently last (and so doesn't have a trailing semicolon) won't
        // match if it's later in a non-final position. The same is true of
        // the first cookie.
        if (i == 0 && cookie_values.size() == 1) {
          cookie = cookie_values[i].as_string();
        } else if (i == 0) {
          cookie = cookie_values[i].as_string() + ";";
        } else if (i < cookie_values.size() - 1) {
          cookie = " " + cookie_values[i].as_string() + ";";
        } else {
          cookie = " " + cookie_values[i].as_string();
        }
        WriteZ(cookie, kZCookieData, z);
      }
    } else if (it->first == "accept" ||
               it->first == "accept-charset" ||
               it->first == "accept-encoding" ||
               it->first == "accept-language" ||
               it->first == "host" ||
               it->first == "version" ||
               it->first == "method" ||
               it->first == "scheme" ||
               it->first == ":host" ||
               it->first == ":version" ||
               it->first == ":method" ||
               it->first == ":scheme" ||
               it->first == "user-agent") {
      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
      WriteZ(it->second, kZStandardData, z);
    } else {
      // Non-whitelisted headers are Huffman compressed in their own block, but
      // don't match against the window.
      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
      WriteZ(it->second, kZHuffmanOnlyData, z);
    }
  }

  z->avail_in = 0;
  int rv = deflate(z, Z_SYNC_FLUSH);
  DCHECK_EQ(Z_OK, rv);
  z->clas = kZStandardData;
}
#endif  // !defined(USE_SYSTEM_ZLIB)

size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
                                                        size_t len) {
  DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
  size_t original_len = len;

  if (remaining_control_header_ > 0) {
    size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
                                                 remaining_control_header_);
    remaining_control_header_ -= bytes_read;
    remaining_data_length_ -= bytes_read;
  }

  if (remaining_control_header_ == 0) {
    SpdyFrameReader reader(current_frame_buffer_.get(),
                           current_frame_buffer_length_);
    reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.

    switch (current_frame_type_) {
      case SYN_STREAM:
        {
          bool successful_read = true;
          if (spdy_version_ < 4) {
            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
            DCHECK(successful_read);
          }
          if (current_frame_stream_id_ == 0) {
            set_error(SPDY_INVALID_CONTROL_FRAME);
            break;
          }

          SpdyStreamId associated_to_stream_id = kInvalidStream;
          successful_read = reader.ReadUInt31(&associated_to_stream_id);
          DCHECK(successful_read);

          SpdyPriority priority = 0;
          successful_read = reader.ReadUInt8(&priority);
          DCHECK(successful_read);
          if (protocol_version() < 3) {
            priority = priority >> 6;
          } else {
            priority = priority >> 5;
          }

          uint8 slot = 0;
          if (protocol_version() < 3) {
            // SPDY 2 had an unused byte here. Seek past it.
            reader.Seek(1);
          } else {
            successful_read = reader.ReadUInt8(&slot);
            DCHECK(successful_read);
          }

          DCHECK(reader.IsDoneReading());
          if (debug_visitor_) {
            debug_visitor_->OnReceiveCompressedFrame(
                current_frame_stream_id_,
                current_frame_type_,
                current_frame_length_);
          }
          visitor_->OnSynStream(
              current_frame_stream_id_,
              associated_to_stream_id,
              priority,
              slot,
              (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
              (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
        }
        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
        break;
      case SETTINGS:
        visitor_->OnSettings(current_frame_flags_ &
                             SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
        CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
        break;
      case SYN_REPLY:
      case HEADERS:
        // SYN_REPLY and HEADERS are the same, save for the visitor call.
        {
          bool successful_read = true;
          if (spdy_version_ < 4) {
            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
            DCHECK(successful_read);
          }
          if (current_frame_stream_id_ == 0) {
            set_error(SPDY_INVALID_CONTROL_FRAME);
            break;
          }
          if (protocol_version() < 3) {
            // SPDY 2 had two unused bytes here. Seek past them.
            reader.Seek(2);
          }
          DCHECK(reader.IsDoneReading());
          if (debug_visitor_) {
            debug_visitor_->OnReceiveCompressedFrame(
                current_frame_stream_id_,
                current_frame_type_,
                current_frame_length_);
          }
          if (current_frame_type_ == SYN_REPLY) {
            visitor_->OnSynReply(
                current_frame_stream_id_,
                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
          } else {
            visitor_->OnHeaders(
                current_frame_stream_id_,
                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
          }
        }
        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
        break;
      case PUSH_PROMISE:
        {
          DCHECK_LE(4, protocol_version());
          if (current_frame_stream_id_ == 0) {
            set_error(SPDY_INVALID_CONTROL_FRAME);
            break;
          }
          SpdyStreamId promised_stream_id = kInvalidStream;
          bool successful_read = reader.ReadUInt31(&promised_stream_id);
          DCHECK(successful_read);
          DCHECK(reader.IsDoneReading());
          if (promised_stream_id == 0) {
            set_error(SPDY_INVALID_CONTROL_FRAME);
            break;
          }
          if (debug_visitor_) {
            debug_visitor_->OnReceiveCompressedFrame(
                current_frame_stream_id_,
                current_frame_type_,
                current_frame_length_);
          }
          visitor_->OnPushPromise(current_frame_stream_id_, promised_stream_id);
        }
        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
        break;
      default:
        DCHECK(false);
    }
  }
  return original_len - len;
}

// Does not buffer the control payload. Instead, either passes directly to the
// visitor or decompresses and then passes directly to the visitor, via
// IncrementallyDeliverControlFrameHeaderData() or
// IncrementallyDecompressControlFrameHeaderData() respectively.
size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
                                                  size_t data_len) {
  DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);

  bool processed_successfully = true;
  if (current_frame_type_ != SYN_STREAM &&
      current_frame_type_ != SYN_REPLY &&
      current_frame_type_ != HEADERS &&
      current_frame_type_ != PUSH_PROMISE) {
    LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
  }
  size_t process_bytes = std::min(data_len, remaining_data_length_);
  if (process_bytes > 0) {
    if (enable_compression_) {
      processed_successfully = IncrementallyDecompressControlFrameHeaderData(
          current_frame_stream_id_, data, process_bytes);
    } else {
      processed_successfully = IncrementallyDeliverControlFrameHeaderData(
          current_frame_stream_id_, data, process_bytes);
    }

    remaining_data_length_ -= process_bytes;
  }

  // Handle the case that there is no futher data in this frame.
  if (remaining_data_length_ == 0 && processed_successfully) {
    // The complete header block has been delivered. We send a zero-length
    // OnControlFrameHeaderData() to indicate this.
    visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);

    // If this is a FIN, tell the caller.
    if (current_frame_flags_ & CONTROL_FLAG_FIN) {
      visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
    }

    CHANGE_STATE(SPDY_AUTO_RESET);
  }

  // Handle error.
  if (!processed_successfully) {
    return data_len;
  }

  // Return amount processed.
  return process_bytes;
}

size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
                                               size_t data_len) {
  DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
  DCHECK_EQ(SETTINGS, current_frame_type_);
  size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
  size_t processed_bytes = 0;

  // Loop over our incoming data.
  while (unprocessed_bytes > 0) {
    // Process up to one setting at a time.
    size_t processing = std::min(
        unprocessed_bytes,
        static_cast<size_t>(8 - settings_scratch_.setting_buf_len));

    // Check if we have a complete setting in our input.
    if (processing == 8) {
      // Parse the setting directly out of the input without buffering.
      if (!ProcessSetting(data + processed_bytes)) {
        set_error(SPDY_INVALID_CONTROL_FRAME);
        return processed_bytes;
      }
    } else {
      // Continue updating settings_scratch_.setting_buf.
      memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
             data + processed_bytes,
             processing);
      settings_scratch_.setting_buf_len += processing;

      // Check if we have a complete setting buffered.
      if (settings_scratch_.setting_buf_len == 8) {
        if (!ProcessSetting(settings_scratch_.setting_buf)) {
          set_error(SPDY_INVALID_CONTROL_FRAME);
          return processed_bytes;
        }
        // Reset settings_scratch_.setting_buf for our next setting.
        settings_scratch_.setting_buf_len = 0;
      }
    }

    // Iterate.
    unprocessed_bytes -= processing;
    processed_bytes += processing;
  }

  // Check if we're done handling this SETTINGS frame.
  remaining_data_length_ -= processed_bytes;
  if (remaining_data_length_ == 0) {
    CHANGE_STATE(SPDY_AUTO_RESET);
  }

  return processed_bytes;
}

bool SpdyFramer::ProcessSetting(const char* data) {
  // Extract fields.
  // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
  const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
  SettingsFlagsAndId id_and_flags =
      SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
  uint8 flags = id_and_flags.flags();
  uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));

  // Validate id.
  switch (id_and_flags.id()) {
    case SETTINGS_UPLOAD_BANDWIDTH:
    case SETTINGS_DOWNLOAD_BANDWIDTH:
    case SETTINGS_ROUND_TRIP_TIME:
    case SETTINGS_MAX_CONCURRENT_STREAMS:
    case SETTINGS_CURRENT_CWND:
    case SETTINGS_DOWNLOAD_RETRANS_RATE:
    case SETTINGS_INITIAL_WINDOW_SIZE:
      // Valid values.
      break;
    default:
      DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
      return false;
  }
  SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());

  // Detect duplciates.
  if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
    DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
                  << " in " << display_protocol_ << " SETTINGS frame "
                  << "(last settikng id was "
                  << settings_scratch_.last_setting_id << ").";
    return false;
  }
  settings_scratch_.last_setting_id = id;

  // Validate flags.
  uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
  if ((flags & ~(kFlagsMask)) != 0) {
    DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
                  << flags;
    return false;
  }

  // Validation succeeded. Pass on to visitor.
  visitor_->OnSetting(id, flags, value);
  return true;
}

size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
  size_t original_len = len;
  size_t bytes_read =
      UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_);
  remaining_data_length_ -= bytes_read;
  if (remaining_data_length_ == 0) {
    SpdyFrameReader reader(current_frame_buffer_.get(),
                           current_frame_buffer_length_);
    reader.Seek(GetControlFrameHeaderSize());  // Skip frame header.

    // Use frame-specific handlers.
    switch (current_frame_type_) {
      case RST_STREAM: {
          bool successful_read = true;
          if (spdy_version_ < 4) {
            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
            DCHECK(successful_read);
          }
          SpdyRstStreamStatus status = RST_STREAM_INVALID;
          uint32 status_raw = status;
          successful_read = reader.ReadUInt32(&status_raw);
          DCHECK(successful_read);
          if (status_raw > RST_STREAM_INVALID &&
              status_raw < RST_STREAM_NUM_STATUS_CODES) {
            status = static_cast<SpdyRstStreamStatus>(status_raw);
          } else {
            // TODO(hkhalil): Probably best to OnError here, depending on
            // our interpretation of the spec. Keeping with existing liberal
            // behavior for now.
          }
          DCHECK(reader.IsDoneReading());
          visitor_->OnRstStream(current_frame_stream_id_, status);
        }
        break;
      case PING: {
          SpdyPingId id = 0;
          bool successful_read = reader.ReadUInt32(&id);
          DCHECK(successful_read);
          DCHECK(reader.IsDoneReading());
          visitor_->OnPing(id);
        }
        break;
      case GOAWAY: {
          bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
          DCHECK(successful_read);
          SpdyGoAwayStatus status = GOAWAY_OK;
          if (spdy_version_ >= 3) {
            uint32 status_raw = GOAWAY_OK;
            successful_read = reader.ReadUInt32(&status_raw);
            DCHECK(successful_read);
            if (status_raw >= GOAWAY_OK &&
                status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) {
              status = static_cast<SpdyGoAwayStatus>(status_raw);
            } else {
              // TODO(hkhalil): Probably best to OnError here, depending on
              // our interpretation of the spec. Keeping with existing liberal
              // behavior for now.
            }
          }
          DCHECK(reader.IsDoneReading());
          visitor_->OnGoAway(current_frame_stream_id_, status);
        }
        break;
      case WINDOW_UPDATE: {
          uint32 delta_window_size = 0;
          bool successful_read = true;
          if (spdy_version_ < 4) {
            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
            DCHECK(successful_read);
          }
          successful_read = reader.ReadUInt32(&delta_window_size);
          DCHECK(successful_read);
          DCHECK(reader.IsDoneReading());
          visitor_->OnWindowUpdate(current_frame_stream_id_,
                                   delta_window_size);
        }
        break;
      case BLOCKED: {
          DCHECK_LE(4, protocol_version());
          DCHECK(reader.IsDoneReading());
          visitor_->OnBlocked(current_frame_stream_id_);
        }
        break;
      default:
        // Unreachable.
        LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
    }

    CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
  }
  return original_len - len;
}

size_t SpdyFramer::ProcessCredentialFramePayload(const char* data, size_t len) {
  if (len > 0) {
    // Clamp to the actual remaining payload.
    if (len > remaining_data_length_) {
      len = remaining_data_length_;
    }
    bool processed_succesfully = visitor_->OnCredentialFrameData(data, len);
    remaining_data_length_ -= len;
    if (!processed_succesfully) {
      set_error(SPDY_CREDENTIAL_FRAME_CORRUPT);
    } else if (remaining_data_length_ == 0) {
      visitor_->OnCredentialFrameData(NULL, 0);
      CHANGE_STATE(SPDY_AUTO_RESET);
    }
  }
  return len;
}

size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
  size_t original_len = len;

  if (remaining_data_length_ > 0) {
    size_t amount_to_forward = std::min(remaining_data_length_, len);
    if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
      // Only inform the visitor if there is data.
      if (amount_to_forward) {
        visitor_->OnStreamFrameData(
            current_frame_stream_id_, data, amount_to_forward, false);
      }
    }
    data += amount_to_forward;
    len -= amount_to_forward;
    remaining_data_length_ -= amount_to_forward;

    // If the FIN flag is set, and there is no more data in this data
    // frame, inform the visitor of EOF via a 0-length data frame.
    if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
      visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
    }
  }

  if (remaining_data_length_ == 0) {
    CHANGE_STATE(SPDY_AUTO_RESET);
  }
  return original_len - len;
}

size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
                                          size_t header_length,
                                          SpdyHeaderBlock* block) const {
  SpdyFrameReader reader(header_data, header_length);

  // Read number of headers.
  uint32 num_headers;
  if (spdy_version_ < 3) {
    uint16 temp;
    if (!reader.ReadUInt16(&temp)) {
      DVLOG(1) << "Unable to read number of headers.";
      return 0;
    }
    num_headers = temp;
  } else {
    if (!reader.ReadUInt32(&num_headers)) {
      DVLOG(1) << "Unable to read number of headers.";
      return 0;
    }
  }

  // Read each header.
  for (uint32 index = 0; index < num_headers; ++index) {
    base::StringPiece temp;

    // Read header name.
    if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
                            : !reader.ReadStringPiece32(&temp)) {
      DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
               << num_headers << ").";
      return 0;
    }
    std::string name = temp.as_string();

    // Read header value.
    if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
                            : !reader.ReadStringPiece32(&temp)) {
      DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
               << num_headers << ").";
      return 0;
    }
    std::string value = temp.as_string();

    // Ensure no duplicates.
    if (block->find(name) != block->end()) {
      DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
               << num_headers << ").";
      return 0;
    }

    // Store header.
    (*block)[name] = value;
  }
  return reader.GetBytesConsumed();
}

/* static */
bool SpdyFramer::ParseCredentialData(const char* data, size_t len,
                                     SpdyCredential* credential) {
  DCHECK(credential);

  SpdyFrameReader parser(data, len);
  base::StringPiece temp;
  if (!parser.ReadUInt16(&credential->slot)) {
    return false;
  }

  if (!parser.ReadStringPiece32(&temp)) {
    return false;
  }
  credential->proof = temp.as_string();

  while (!parser.IsDoneReading()) {
    if (!parser.ReadStringPiece32(&temp)) {
      return false;
    }
    credential->certs.push_back(temp.as_string());
  }
  return true;
}

SpdyFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
                                       const char* data,
                                       uint32 len, SpdyDataFlags flags) const {
  DCHECK_EQ(0, flags & (!DATA_FLAG_FIN));

  SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
  data_ir.set_fin(flags & DATA_FLAG_FIN);
  return SerializeData(data_ir);
}

SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
  const size_t kSize = GetDataFrameMinimumSize() + data.data().length();

  SpdyDataFlags flags = DATA_FLAG_NONE;
  if (data.fin()) {
    flags = DATA_FLAG_FIN;
  }

  SpdyFrameBuilder builder(kSize);
  builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
  builder.WriteBytes(data.data().data(), data.data().length());
  DCHECK_EQ(kSize, builder.length());
  return builder.take();
}

SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
    const SpdyDataIR& data) const {
  const size_t kSize = GetDataFrameMinimumSize();

  SpdyDataFlags flags = DATA_FLAG_NONE;
  if (data.fin()) {
    flags = DATA_FLAG_FIN;
  }

  SpdyFrameBuilder builder(kSize);
  builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
  if (protocol_version() < 4) {
    builder.OverwriteLength(*this, data.data().length());
  } else {
    builder.OverwriteLength(*this, data.data().length() + kSize);
  }
  DCHECK_EQ(kSize, builder.length());
  return builder.take();
}

SpdyFrame* SpdyFramer::CreateSynStream(
    SpdyStreamId stream_id,
    SpdyStreamId associated_stream_id,
    SpdyPriority priority,
    uint8 credential_slot,
    SpdyControlFlags flags,
    const SpdyHeaderBlock* headers) {
  DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL);

  SpdySynStreamIR syn_stream(stream_id);
  syn_stream.set_associated_to_stream_id(associated_stream_id);
  syn_stream.set_priority(priority);
  syn_stream.set_slot(credential_slot);
  syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
  syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
  // TODO(hkhalil): Avoid copy here.
  *(syn_stream.GetMutableNameValueBlock()) = *headers;

  return SerializeSynStream(syn_stream);
}

SpdySerializedFrame* SpdyFramer::SerializeSynStream(
    const SpdySynStreamIR& syn_stream) {
  uint8 flags = 0;
  if (syn_stream.fin()) {
    flags |= CONTROL_FLAG_FIN;
  }
  if (syn_stream.unidirectional()) {
    flags |= CONTROL_FLAG_UNIDIRECTIONAL;
  }

  // The size of this frame, including variable-length name-value block.
  const size_t size = GetSynStreamMinimumSize()
      + GetSerializedLength(syn_stream.name_value_block());

  SpdyFrameBuilder builder(size);
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
    builder.WriteUInt32(syn_stream.stream_id());
  } else {
    builder.WriteFramePrefix(*this,
                             SYN_STREAM,
                             flags,
                             syn_stream.stream_id());
  }
  builder.WriteUInt32(syn_stream.associated_to_stream_id());
  uint8 priority = syn_stream.priority();
  if (priority > GetLowestPriority()) {
    DLOG(DFATAL) << "Priority out-of-bounds.";
    priority = GetLowestPriority();
  }
  builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
  builder.WriteUInt8(syn_stream.slot());
  DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
  SerializeNameValueBlock(&builder, syn_stream);

  if (debug_visitor_) {
    const size_t payload_len = GetSerializedLength(
        protocol_version(), &(syn_stream.name_value_block()));
    debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
                                          SYN_STREAM,
                                          payload_len,
                                          builder.length());
  }

  return builder.take();
}

SpdyFrame* SpdyFramer::CreateSynReply(
    SpdyStreamId stream_id,
    SpdyControlFlags flags,
    const SpdyHeaderBlock* headers) {
  DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN);

  SpdySynReplyIR syn_reply(stream_id);
  syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
  // TODO(hkhalil): Avoid copy here.
  *(syn_reply.GetMutableNameValueBlock()) = *headers;

  return SerializeSynReply(syn_reply);
}

SpdySerializedFrame* SpdyFramer::SerializeSynReply(
    const SpdySynReplyIR& syn_reply) {
  uint8 flags = 0;
  if (syn_reply.fin()) {
    flags |= CONTROL_FLAG_FIN;
  }

  // The size of this frame, including variable-length name-value block.
  size_t size = GetSynReplyMinimumSize()
      + GetSerializedLength(syn_reply.name_value_block());

  SpdyFrameBuilder builder(size);
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
    builder.WriteUInt32(syn_reply.stream_id());
  } else {
    builder.WriteFramePrefix(*this,
                             SYN_REPLY,
                             flags,
                             syn_reply.stream_id());
  }
  if (protocol_version() < 3) {
    builder.WriteUInt16(0);  // Unused.
  }
  DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
  SerializeNameValueBlock(&builder, syn_reply);

  if (debug_visitor_) {
    const size_t payload_len = GetSerializedLength(
        protocol_version(), &(syn_reply.name_value_block()));
    debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
                                          SYN_REPLY,
                                          payload_len,
                                          builder.length());
  }

  return builder.take();
}

SpdyFrame* SpdyFramer::CreateRstStream(
    SpdyStreamId stream_id,
    SpdyRstStreamStatus status) const {
  SpdyRstStreamIR rst_stream(stream_id, status);
  return SerializeRstStream(rst_stream);
}

SpdySerializedFrame* SpdyFramer::SerializeRstStream(
    const SpdyRstStreamIR& rst_stream) const {
  SpdyFrameBuilder builder(GetRstStreamSize());
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
    builder.WriteUInt32(rst_stream.stream_id());
  } else {
    builder.WriteFramePrefix(*this,
                             RST_STREAM,
                             0,
                             rst_stream.stream_id());
  }
  builder.WriteUInt32(rst_stream.status());
  DCHECK_EQ(GetRstStreamSize(), builder.length());
  return builder.take();
}

SpdyFrame* SpdyFramer::CreateSettings(
    const SettingsMap& values) const {
  SpdySettingsIR settings;
  for (SettingsMap::const_iterator it = values.begin();
       it != values.end();
       ++it) {
    settings.AddSetting(it->first,
                        (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
                        (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
                        it->second.second);
  }
  return SerializeSettings(settings);
}

SpdySerializedFrame* SpdyFramer::SerializeSettings(
    const SpdySettingsIR& settings) const {
  uint8 flags = 0;
  if (settings.clear_settings()) {
    flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
  }
  const SpdySettingsIR::ValueMap* values = &(settings.values());

  // Size, in bytes, of this SETTINGS frame.
  const size_t size = GetSettingsMinimumSize() + (values->size() * 8);

  SpdyFrameBuilder builder(size);
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, SETTINGS, flags);
  } else {
    builder.WriteFramePrefix(*this, SETTINGS, flags, 0);
  }
  builder.WriteUInt32(values->size());
  DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
  for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
       it != values->end();
       ++it) {
    uint8 setting_flags = 0;
    if (it->second.persist_value) {
      setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
    }
    if (it->second.persisted) {
      setting_flags |= SETTINGS_FLAG_PERSISTED;
    }
    SettingsFlagsAndId flags_and_id(setting_flags, it->first);
    uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
    builder.WriteBytes(&id_and_flags_wire, 4);
    builder.WriteUInt32(it->second.value);
  }
  DCHECK_EQ(size, builder.length());
  return builder.take();
}

SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
  DCHECK_LE(4, protocol_version());
  SpdyFrameBuilder builder(GetBlockedSize());
  builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id());
  return builder.take();
}

SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const {
  SpdyPingIR ping(unique_id);
  return SerializePing(ping);
}

SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
  SpdyFrameBuilder builder(GetPingSize());
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, PING, kNoFlags);
  } else {
    builder.WriteFramePrefix(*this, PING, 0, 0);
  }
  builder.WriteUInt32(ping.id());
  DCHECK_EQ(GetPingSize(), builder.length());
  return builder.take();
}

SpdyFrame* SpdyFramer::CreateGoAway(
    SpdyStreamId last_accepted_stream_id,
    SpdyGoAwayStatus status) const {
  SpdyGoAwayIR goaway(last_accepted_stream_id, status);
  return SerializeGoAway(goaway);
}

SpdySerializedFrame* SpdyFramer::SerializeGoAway(
    const SpdyGoAwayIR& goaway) const {
  SpdyFrameBuilder builder(GetGoAwaySize());
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
  } else {
    builder.WriteFramePrefix(*this, GOAWAY, 0, 0);
  }
  builder.WriteUInt32(goaway.last_good_stream_id());
  if (protocol_version() >= 3) {
    builder.WriteUInt32(goaway.status());
  }
  DCHECK_EQ(GetGoAwaySize(), builder.length());
  return builder.take();
}

SpdyFrame* SpdyFramer::CreateHeaders(
    SpdyStreamId stream_id,
    SpdyControlFlags flags,
    const SpdyHeaderBlock* header_block) {
  // Basically the same as CreateSynReply().
  DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN));

  SpdyHeadersIR headers(stream_id);
  headers.set_fin(flags & CONTROL_FLAG_FIN);
  // TODO(hkhalil): Avoid copy here.
  *(headers.GetMutableNameValueBlock()) = *header_block;

  return SerializeHeaders(headers);
}

SpdySerializedFrame* SpdyFramer::SerializeHeaders(
    const SpdyHeadersIR& headers) {
  uint8 flags = 0;
  if (headers.fin()) {
    flags |= CONTROL_FLAG_FIN;
  }

  // The size of this frame, including variable-length name-value block.
  size_t size = GetHeadersMinimumSize()
      + GetSerializedLength(headers.name_value_block());

  SpdyFrameBuilder builder(size);
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, HEADERS, flags);
    builder.WriteUInt32(headers.stream_id());
  } else {
    builder.WriteFramePrefix(*this,
                             HEADERS,
                             flags,
                             headers.stream_id());
  }
  if (protocol_version() < 3) {
    builder.WriteUInt16(0);  // Unused.
  }
  DCHECK_EQ(GetHeadersMinimumSize(), builder.length());

  SerializeNameValueBlock(&builder, headers);

  if (debug_visitor_) {
    const size_t payload_len = GetSerializedLength(
        protocol_version(), &(headers.name_value_block()));
    debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
                                          HEADERS,
                                          payload_len,
                                          builder.length());
  }

  return builder.take();
}

SpdyFrame* SpdyFramer::CreateWindowUpdate(
    SpdyStreamId stream_id,
    uint32 delta_window_size) const {
  SpdyWindowUpdateIR window_update(stream_id, delta_window_size);
  return SerializeWindowUpdate(window_update);
}

SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
    const SpdyWindowUpdateIR& window_update) const {
  SpdyFrameBuilder builder(GetWindowUpdateSize());
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
    builder.WriteUInt32(window_update.stream_id());
  } else {
    builder.WriteFramePrefix(*this,
                             WINDOW_UPDATE,
                             kNoFlags,
                             window_update.stream_id());
  }
  builder.WriteUInt32(window_update.delta());
  DCHECK_EQ(GetWindowUpdateSize(), builder.length());
  return builder.take();
}

// TODO(hkhalil): Gut with SpdyCredential removal.
SpdyFrame* SpdyFramer::CreateCredentialFrame(
    const SpdyCredential& credential) const {
  SpdyCredentialIR credential_ir(credential.slot);
  credential_ir.set_proof(credential.proof);
  for (std::vector<std::string>::const_iterator cert = credential.certs.begin();
       cert != credential.certs.end();
       ++cert) {
    credential_ir.AddCertificate(*cert);
  }
  return SerializeCredential(credential_ir);
}

SpdySerializedFrame* SpdyFramer::SerializeCredential(
    const SpdyCredentialIR& credential) const {
  size_t size = GetCredentialMinimumSize();
  size += 4 + credential.proof().length();  // Room for proof.
  for (SpdyCredentialIR::CertificateList::const_iterator it =
       credential.certificates()->begin();
       it != credential.certificates()->end();
       ++it) {
    size += 4 + it->length();  // Room for certificate.
  }

  SpdyFrameBuilder builder(size);
  if (spdy_version_ < 4) {
    builder.WriteControlFrameHeader(*this, CREDENTIAL, kNoFlags);
  } else {
    builder.WriteFramePrefix(*this, CREDENTIAL, kNoFlags, 0);
  }
  builder.WriteUInt16(credential.slot());
  DCHECK_EQ(GetCredentialMinimumSize(), builder.length());
  builder.WriteStringPiece32(credential.proof());
  for (SpdyCredentialIR::CertificateList::const_iterator it =
       credential.certificates()->begin();
       it != credential.certificates()->end();
       ++it) {
    builder.WriteStringPiece32(*it);
  }
  DCHECK_EQ(size, builder.length());
  return builder.take();
}

SpdyFrame* SpdyFramer::CreatePushPromise(
    SpdyStreamId stream_id,
    SpdyStreamId promised_stream_id,
    const SpdyHeaderBlock* header_block) {
  SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
  // TODO(hkhalil): Avoid copy here.
  *(push_promise.GetMutableNameValueBlock()) = *header_block;

  return SerializePushPromise(push_promise);
}

SpdyFrame* SpdyFramer::SerializePushPromise(
    const SpdyPushPromiseIR& push_promise) {
  DCHECK_LE(4, protocol_version());
  // The size of this frame, including variable-length name-value block.
  size_t size = GetPushPromiseMinimumSize()
      + GetSerializedLength(push_promise.name_value_block());

  SpdyFrameBuilder builder(size);
  builder.WriteFramePrefix(*this, PUSH_PROMISE, kNoFlags,
                           push_promise.stream_id());
  builder.WriteUInt32(push_promise.promised_stream_id());
  DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());

  SerializeNameValueBlock(&builder, push_promise);

  if (debug_visitor_) {
    const size_t payload_len = GetSerializedLength(
        protocol_version(), &(push_promise.name_value_block()));
    debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
        PUSH_PROMISE, payload_len, builder.length());
  }

  return builder.take();
}

namespace {

class FrameSerializationVisitor : public SpdyFrameVisitor {
 public:
  explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
  virtual ~FrameSerializationVisitor() {}

  SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }

  virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
    frame_.reset(framer_->SerializeData(data));
  }
  virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
    frame_.reset(framer_->SerializeSynStream(syn_stream));
  }
  virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
    frame_.reset(framer_->SerializeSynReply(syn_reply));
  }
  virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
    frame_.reset(framer_->SerializeRstStream(rst_stream));
  }
  virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
    frame_.reset(framer_->SerializeSettings(settings));
  }
  virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
    frame_.reset(framer_->SerializePing(ping));
  }
  virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
    frame_.reset(framer_->SerializeGoAway(goaway));
  }
  virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
    frame_.reset(framer_->SerializeHeaders(headers));
  }
  virtual void VisitWindowUpdate(
      const SpdyWindowUpdateIR& window_update) OVERRIDE {
    frame_.reset(framer_->SerializeWindowUpdate(window_update));
  }
  virtual void VisitCredential(const SpdyCredentialIR& credential) OVERRIDE {
    frame_.reset(framer_->SerializeCredential(credential));
  }
  virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
    frame_.reset(framer_->SerializeBlocked(blocked));
  }
  virtual void VisitPushPromise(
      const SpdyPushPromiseIR& push_promise) OVERRIDE {
    frame_.reset(framer_->SerializePushPromise(push_promise));
  }

 private:
  SpdyFramer* framer_;
  scoped_ptr<SpdySerializedFrame> frame_;
};

}  // namespace

SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
  FrameSerializationVisitor visitor(this);
  frame.Visit(&visitor);
  return visitor.ReleaseSerializedFrame();
}

size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
  const size_t uncompressed_length =
      GetSerializedLength(protocol_version(), &headers);
  if (!enable_compression_) {
    return uncompressed_length;
  }
  z_stream* compressor = GetHeaderCompressor();
  // Since we'll be performing lots of flushes when compressing the data,
  // zlib's lower bounds may be insufficient.
  return 2 * deflateBound(compressor, uncompressed_length);
}

// The following compression setting are based on Brian Olson's analysis. See
// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
// for more details.
#if defined(USE_SYSTEM_ZLIB)
// System zlib is not expected to have workaround for http://crbug.com/139744,
// so disable compression in that case.
// TODO(phajdan.jr): Remove the special case when it's no longer necessary.
static const int kCompressorLevel = 0;
#else  // !defined(USE_SYSTEM_ZLIB)
static const int kCompressorLevel = 9;
#endif  // !defined(USE_SYSTEM_ZLIB)
static const int kCompressorWindowSizeInBits = 11;
static const int kCompressorMemLevel = 1;

z_stream* SpdyFramer::GetHeaderCompressor() {
  if (header_compressor_.get())
    return header_compressor_.get();  // Already initialized.

  header_compressor_.reset(new z_stream);
  memset(header_compressor_.get(), 0, sizeof(z_stream));

  int success = deflateInit2(header_compressor_.get(),
                             kCompressorLevel,
                             Z_DEFLATED,
                             kCompressorWindowSizeInBits,
                             kCompressorMemLevel,
                             Z_DEFAULT_STRATEGY);
  if (success == Z_OK) {
    const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
                                                 : kV3Dictionary;
    const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
                                                    : kV3DictionarySize;
    success = deflateSetDictionary(header_compressor_.get(),
                                   reinterpret_cast<const Bytef*>(dictionary),
                                   dictionary_size);
  }
  if (success != Z_OK) {
    LOG(WARNING) << "deflateSetDictionary failure: " << success;
    header_compressor_.reset(NULL);
    return NULL;
  }
  return header_compressor_.get();
}

z_stream* SpdyFramer::GetHeaderDecompressor() {
  if (header_decompressor_.get())
    return header_decompressor_.get();  // Already initialized.

  header_decompressor_.reset(new z_stream);
  memset(header_decompressor_.get(), 0, sizeof(z_stream));

  int success = inflateInit(header_decompressor_.get());
  if (success != Z_OK) {
    LOG(WARNING) << "inflateInit failure: " << success;
    header_decompressor_.reset(NULL);
    return NULL;
  }
  return header_decompressor_.get();
}

// Incrementally decompress the control frame's header block, feeding the
// result to the visitor in chunks. Continue this until the visitor
// indicates that it cannot process any more data, or (more commonly) we
// run out of data to deliver.
bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
    SpdyStreamId stream_id,
    const char* data,
    size_t len) {
  // Get a decompressor or set error.
  z_stream* decomp = GetHeaderDecompressor();
  if (decomp == NULL) {
    LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
    set_error(SPDY_DECOMPRESS_FAILURE);
    return false;
  }

  bool processed_successfully = true;
  char buffer[kHeaderDataChunkMaxSize];

  decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
  decomp->avail_in = len;
  // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
  // signal an error back in ProcessControlFrameBeforeHeaderBlock.  So if we've
  // reached this method successfully, stream_id should be nonzero.
  DCHECK_LT(0u, stream_id);
  while (decomp->avail_in > 0 && processed_successfully) {
    decomp->next_out = reinterpret_cast<Bytef*>(buffer);
    decomp->avail_out = arraysize(buffer);

    int rv = inflate(decomp, Z_SYNC_FLUSH);
    if (rv == Z_NEED_DICT) {
      const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
                                                   : kV3Dictionary;
      const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
                                                      : kV3DictionarySize;
      const DictionaryIds& ids = g_dictionary_ids.Get();
      const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
                                                      : ids.v3_dictionary_id;
      // Need to try again with the right dictionary.
      if (decomp->adler == dictionary_id) {
        rv = inflateSetDictionary(decomp,
                                  reinterpret_cast<const Bytef*>(dictionary),
                                  dictionary_size);
        if (rv == Z_OK)
          rv = inflate(decomp, Z_SYNC_FLUSH);
      }
    }

    // Inflate will generate a Z_BUF_ERROR if it runs out of input
    // without producing any output.  The input is consumed and
    // buffered internally by zlib so we can detect this condition by
    // checking if avail_in is 0 after the call to inflate.
    bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
    if ((rv == Z_OK) || input_exhausted) {
      size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
      if (decompressed_len > 0) {
        processed_successfully = visitor_->OnControlFrameHeaderData(
            stream_id, buffer, decompressed_len);
      }
      if (!processed_successfully) {
        // Assume that the problem was the header block was too large for the
        // visitor.
        set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
      }
    } else {
      DLOG(WARNING) << "inflate failure: " << rv << " " << len;
      set_error(SPDY_DECOMPRESS_FAILURE);
      processed_successfully = false;
    }
  }
  return processed_successfully;
}

bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
    SpdyStreamId stream_id, const char* data, size_t len) {
  bool read_successfully = true;
  while (read_successfully && len > 0) {
    size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
    read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
                                                           bytes_to_deliver);
    data += bytes_to_deliver;
    len -= bytes_to_deliver;
    if (!read_successfully) {
      // Assume that the problem was the header block was too large for the
      // visitor.
      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
    }
  }
  return read_successfully;
}

void SpdyFramer::SerializeNameValueBlockWithoutCompression(
    SpdyFrameBuilder* builder,
    const SpdyNameValueBlock& name_value_block) const {
  // Serialize number of headers.
  if (protocol_version() < 3) {
    builder->WriteUInt16(name_value_block.size());
  } else {
    builder->WriteUInt32(name_value_block.size());
  }

  // Serialize each header.
  for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
       it != name_value_block.end();
       ++it) {
    if (protocol_version() < 3) {
      builder->WriteString(it->first);
      builder->WriteString(it->second);
    } else {
      builder->WriteStringPiece32(it->first);
      builder->WriteStringPiece32(it->second);
    }
  }
}

void SpdyFramer::SerializeNameValueBlock(
    SpdyFrameBuilder* builder,
    const SpdyFrameWithNameValueBlockIR& frame) {
  if (!enable_compression_) {
    return SerializeNameValueBlockWithoutCompression(builder,
                                                     frame.name_value_block());
  }

  // First build an uncompressed version to be fed into the compressor.
  const size_t uncompressed_len = GetSerializedLength(
      protocol_version(), &(frame.name_value_block()));
  SpdyFrameBuilder uncompressed_builder(uncompressed_len);
  SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
                                            frame.name_value_block());
  scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());

  z_stream* compressor = GetHeaderCompressor();
  if (!compressor) {
    LOG(DFATAL) << "Could not obtain compressor.";
    return;
  }

  base::StatsCounter compressed_frames("spdy.CompressedFrames");
  base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
  base::StatsCounter post_compress_bytes("spdy.PostCompressSize");

  // Create an output frame.
  // Since we'll be performing lots of flushes when compressing the data,
  // zlib's lower bounds may be insufficient.
  //
  // TODO(akalin): Avoid the duplicate calculation with
  // GetSerializedLength(const SpdyHeaderBlock&).
  const int compressed_max_size =
      2 * deflateBound(compressor, uncompressed_len);

  // TODO(phajdan.jr): Clean up after we no longer need
  // to workaround http://crbug.com/139744.
#if defined(USE_SYSTEM_ZLIB)
  compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
  compressor->avail_in = uncompressed_len;
#endif  // defined(USE_SYSTEM_ZLIB)
  compressor->next_out = reinterpret_cast<Bytef*>(
      builder->GetWritableBuffer(compressed_max_size));
  compressor->avail_out = compressed_max_size;

  // TODO(phajdan.jr): Clean up after we no longer need
  // to workaround http://crbug.com/139744.
#if defined(USE_SYSTEM_ZLIB)
  int rv = deflate(compressor, Z_SYNC_FLUSH);
  if (rv != Z_OK) {  // How can we know that it compressed everything?
    // This shouldn't happen, right?
    LOG(WARNING) << "deflate failure: " << rv;
    // TODO(akalin): Upstream this return.
    return;
  }
#else
  WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
#endif  // defined(USE_SYSTEM_ZLIB)

  int compressed_size = compressed_max_size - compressor->avail_out;
  builder->Seek(compressed_size);
  builder->RewriteLength(*this);

  pre_compress_bytes.Add(uncompressed_len);
  post_compress_bytes.Add(compressed_size);

  compressed_frames.Increment();
}

}  // namespace net
