15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rtenhove) clean up frame buffer size calculations so that we aren't
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constantly adding and subtracting header sizes; this is ugly and error-
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prone.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_framer.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/valgrind/memcheck.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_builder.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_reader.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_bitmasks.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/zlib.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Compute the id of our dictionary so that we know we're using the
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// right one when asked for it.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uLong CalculateDictionaryId(const char* dictionary,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const size_t dictionary_size) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uLong initial_value = adler32(0L, Z_NULL, 0);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return adler32(initial_value,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 reinterpret_cast<const Bytef*>(dictionary),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 dictionary_size);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DictionaryIds {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryIds()
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uLong v2_dictionary_id;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uLong v3_dictionary_id;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adler ID for the SPDY header compressor dictionaries. Note that they are
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialized lazily to avoid static initializers.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to indicate no flags in a SPDY flags field.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8 kNoFlags = 0;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SpdyStreamId SpdyFramer::kInvalidStream = -1;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The size of the control frame buffer. Must be >= the minimum size of the
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// calculation details.
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t SpdyFramer::kControlFrameBufferSize = 18;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_SPDY_STATE_CHANGES
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate)                                  \
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {                                                          \
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "Changing state from: "                         \
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << StateToString(state_)                           \
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << " to " << StateToString(newstate) << "\n";      \
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ != SPDY_ERROR);                               \
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(previous_state_, state_);                         \
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;                                   \
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = newstate;                                          \
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate)                                  \
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {                                                          \
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ != SPDY_ERROR);                               \
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(previous_state_, state_);                         \
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;                                   \
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = newstate;                                          \
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      uint32 wire) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version < 3) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertFlagsAndIdForSpdy2(&wire);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : flags_(flags), id_(id & 0x00ffffff) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(1u << 24, id) << "SPDY setting ID too large.";
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 SettingsFlagsAndId::GetWireFormat(int version) const {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version < 3) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertFlagsAndIdForSpdy2(&wire);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return wire;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is used to preserve buggy behavior and works on both
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// little-endian and big-endian hosts.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as vice versa).
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8* wire_array = reinterpret_cast<uint8*>(val);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(wire_array[0], wire_array[3]);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(wire_array[1], wire_array[2]);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::SpdyCredential() : slot(0) {}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::~SpdyCredential() {}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SpdyFramer::SpdyFramer(SpdyMajorVersion version)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : current_frame_buffer_(new char[kControlFrameBufferSize]),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enable_compression_(true),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_(NULL),
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      debug_visitor_(NULL),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_protocol_("SPDY"),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spdy_version_(version),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syn_frame_processed_(false),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      probable_http_response_(false) {
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Reset();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::~SpdyFramer() {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_compressor_.get()) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deflateEnd(header_compressor_.get());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_decompressor_.get()) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inflateEnd(header_decompressor_.get());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::Reset() {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = SPDY_RESET;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  previous_state_ = SPDY_RESET;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_code_ = SPDY_NO_ERROR;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remaining_data_length_ = 0;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remaining_control_header_ = 0;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_buffer_length_ = 0;
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  current_frame_type_ = DATA;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_flags_ = 0;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_length_ = 0;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_stream_id_ = kInvalidStream;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings_scratch_.Reset();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMinimumSize() const {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of the data frame header. Future versions of SPDY
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // will likely vary this, so we allow for the flexibility of a function call
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for this value as opposed to a constant.
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 8;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Size, in bytes, of the control frame header.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetControlFrameHeaderSize() const {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (protocol_version()) {
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case SPDY2:
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case SPDY3:
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case SPDY4:
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 8;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LOG(DFATAL) << "Unhandled SPDY version.";
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynStreamMinimumSize() const {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of a SYN_STREAM frame not including the variable-length
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // name-value block.
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot)
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 10;
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // frame prefix + 4 (associated stream ID) + 1 (priority) + 1 (slot)
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 6;
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynReplyMinimumSize() const {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of a SYN_REPLY frame not including the variable-length
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // name-value block.
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t size = GetControlFrameHeaderSize();
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream IDs)
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += 4;
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In SPDY 2, there were 2 unused bytes before payload.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (protocol_version() < 3) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += 2;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return size;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetRstStreamSize() const {
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Size, in bytes, of a RST_STREAM frame.
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream id) + 4 (status code)
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 8;
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // frame prefix + 4 (status code)
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 4;
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSettingsMinimumSize() const {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of a SETTINGS frame not including the IDs and values
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from the variable-length value block. Calculated as:
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // control frame header + 4 (number of ID/value pairs)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetControlFrameHeaderSize() + 4;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetPingSize() const {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of this PING frame. Calculated as:
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // control frame header + 4 (id)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetControlFrameHeaderSize() + 4;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetGoAwaySize() const {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of this GOAWAY frame. Calculated as:
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // control frame header + 4 (last good stream id)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = GetControlFrameHeaderSize() + 4;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SPDY 3+ GOAWAY frames also contain a status.
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (protocol_version() >= 3) {
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += 4;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return size;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetHeadersMinimumSize() const  {
2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Size, in bytes, of a HEADERS frame not including the variable-length
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // name-value block.
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t size = GetControlFrameHeaderSize();
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream IDs)
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += 4;
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In SPDY 2, there were 2 unused bytes before payload.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (protocol_version() < 3) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += 2;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return size;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetWindowUpdateSize() const {
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Size, in bytes, of a WINDOW_UPDATE frame.
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream id) + 4 (delta)
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 8;
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // frame prefix + 4 (delta)
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 4;
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetCredentialMinimumSize() const {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of a CREDENTIAL frame sans variable-length certificate list
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and proof. Calculated as:
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // control frame header + 2 (slot)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetControlFrameHeaderSize() + 2;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t SpdyFramer::GetBlockedSize() const {
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_LE(4, protocol_version());
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Size, in bytes, of a BLOCKED frame.
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The BLOCKED frame has no payload beyond the control frame header.
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetControlFrameHeaderSize();
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsize_t SpdyFramer::GetPushPromiseMinimumSize() const {
2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_LE(4, protocol_version());
2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Calculated as frame prefix + 4 (promised stream id).
2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return GetControlFrameHeaderSize() + 4;
2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMinimumSize() const {
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMaximumSize() const {
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (protocol_version() < 4) ? 0xffffff : 0xffff;
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMaximumPayload() const {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetFrameMaximumSize() - GetDataFrameMinimumSize();
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StateToString(int state) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_ERROR:
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "ERROR";
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_AUTO_RESET:
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "AUTO_RESET";
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_RESET:
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "RESET";
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_READING_COMMON_HEADER:
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_COMMON_HEADER";
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_FRAME_PAYLOAD:
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CONTROL_FRAME_PAYLOAD";
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_IGNORE_REMAINING_PAYLOAD:
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "IGNORE_REMAINING_PAYLOAD";
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_FORWARD_STREAM_FRAME:
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FORWARD_STREAM_FRAME";
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_FRAME_HEADER_BLOCK:
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CREDENTIAL_FRAME_PAYLOAD:
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_CREDENTIAL_FRAME_PAYLOAD";
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_SETTINGS_FRAME_PAYLOAD:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_SETTINGS_FRAME_PAYLOAD";
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_STATE";
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::set_error(SpdyError error) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(visitor_);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_code_ = error;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHANGE_STATE(SPDY_ERROR);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visitor_->OnError(this);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::ErrorCodeToString(int error_code) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (error_code) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_NO_ERROR:
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "NO_ERROR";
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_INVALID_CONTROL_FRAME:
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_CONTROL_FRAME";
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CONTROL_PAYLOAD_TOO_LARGE";
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_ZLIB_INIT_FAILURE:
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "ZLIB_INIT_FAILURE";
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_UNSUPPORTED_VERSION:
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNSUPPORTED_VERSION";
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_DECOMPRESS_FAILURE:
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "DECOMPRESS_FAILURE";
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_COMPRESS_FAILURE:
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "COMPRESS_FAILURE";
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_INVALID_DATA_FRAME_FLAGS:
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_INVALID_DATA_FRAME_FLAGS";
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SPDY_INVALID_CONTROL_FRAME_FLAGS:
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_ERROR";
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StatusCodeToString(int status_code) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (status_code) {
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INVALID:
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID";
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_PROTOCOL_ERROR:
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "PROTOCOL_ERROR";
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INVALID_STREAM:
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_STREAM";
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_REFUSED_STREAM:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "REFUSED_STREAM";
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_UNSUPPORTED_VERSION:
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNSUPPORTED_VERSION";
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_CANCEL:
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CANCEL";
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INTERNAL_ERROR:
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INTERNAL_ERROR";
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_FLOW_CONTROL_ERROR:
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FLOW_CONTROL_ERROR";
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_STREAM_IN_USE:
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "STREAM_IN_USE";
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_STREAM_ALREADY_CLOSED:
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "STREAM_ALREADY_CLOSED";
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INVALID_CREDENTIALS:
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_CREDENTIALS";
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_FRAME_TOO_LARGE:
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FRAME_TOO_LARGE";
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_STATUS";
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case DATA:
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "DATA";
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_STREAM:
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SYN_STREAM";
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_REPLY:
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SYN_REPLY";
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RST_STREAM:
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "RST_STREAM";
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS:
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SETTINGS";
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NOOP:
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "NOOP";
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PING:
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "PING";
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GOAWAY:
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "GOAWAY";
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HEADERS:
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "HEADERS";
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_UPDATE:
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "WINDOW_UPDATE";
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CREDENTIAL:
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CREDENTIAL";
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case BLOCKED:
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return "BLOCKED";
4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case PUSH_PROMISE:
4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return "PUSH_PROMISE";
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_CONTROL_TYPE";
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(visitor_);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state_) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_ERROR:
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_AUTO_RESET:
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_RESET:
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Reset();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (len > 0) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CHANGE_STATE(SPDY_READING_COMMON_HEADER);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_READING_COMMON_HEADER: {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bytes_read = ProcessCommonHeader(data, len);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
4567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // Control frames that contain header blocks
4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE)
4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // take a different path through the state machine - they
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // will go:
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   2. SPDY_CONTROL_FRAME_HEADER_BLOCK
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // SETTINGS frames take a slightly modified route:
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   2. SPDY_SETTINGS_FRAME_PAYLOAD
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //  All other control frames will use the alternate route directly to
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //  SPDY_CONTROL_FRAME_PAYLOAD
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_SETTINGS_FRAME_PAYLOAD: {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int bytes_read = ProcessSettingsFramePayload(data, len);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int bytes_read = ProcessControlFrameHeaderBlock(data, len);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_CREDENTIAL_FRAME_PAYLOAD: {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bytes_read = ProcessCredentialFramePayload(data, len);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_CONTROL_FRAME_PAYLOAD: {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bytes_read = ProcessControlFramePayload(data, len);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_IGNORE_REMAINING_PAYLOAD:
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // control frame has too-large payload
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // intentional fallthrough
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_FORWARD_STREAM_FRAME: {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bytes_read = ProcessDataFramePayload(data, len);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "Invalid value for " << display_protocol_
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << " framer state: " << state_;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This ensures that we don't infinite-loop if state_ gets an
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // invalid value somehow, such as due to a SpdyFramer getting deleted
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // from a callback it calls.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (state_ != previous_state_);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bottom:
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(len == 0 || state_ == SPDY_ERROR);
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_buffer_length_ == 0 &&
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remaining_data_length_ == 0 &&
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remaining_control_header_ == 0) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "State: " << StateToString(state_);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should only be called when we're in the SPDY_READING_COMMON_HEADER
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // state.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update current frame buffer as needed.
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t bytes_desired =
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetControlFrameHeaderSize() - current_frame_buffer_length_;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Not enough information to do anything meaningful.
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return original_len - len;
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // when processing DATA frames below.
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrameReader> reader(
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new SpdyFrameReader(current_frame_buffer_.get(),
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          current_frame_buffer_length_));
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint16 version = 0;
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_control_frame = false;
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint16 control_frame_type_field = DATA;
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // ProcessControlFrameHeader() will set current_frame_type_ to the
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // correct value if this is a valid control frame.
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  current_frame_type_ = DATA;
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (protocol_version() < 4) {
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool successful_read = reader->ReadUInt16(&version);
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_control_frame = (version & kControlFlagMask) != 0;
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    version &= ~kControlFlagMask;  // Only valid for control frames.
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (is_control_frame) {
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // We check control_frame_type_field's validity in
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // ProcessControlFrameHeader().
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      successful_read = reader->ReadUInt16(&control_frame_type_field);
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reader->Rewind();
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      successful_read = reader->ReadUInt31(&current_frame_stream_id_);
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    successful_read = reader->ReadUInt8(&current_frame_flags_);
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 length_field = 0;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    successful_read = reader->ReadUInt24(&length_field);
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ = length_field;
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    version = protocol_version();
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint16 length_field = 0;
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool successful_read = reader->ReadUInt16(&length_field);
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    current_frame_length_ = length_field;
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint8 control_frame_type_field_uint8 = DATA;
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // We check control_frame_type_field's validity in
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // ProcessControlFrameHeader().
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    control_frame_type_field = control_frame_type_field_uint8;
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    is_control_frame = (control_frame_type_field != DATA);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    successful_read = reader->ReadUInt8(&current_frame_flags_);
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    successful_read = reader->ReadUInt31(&current_frame_stream_id_);
60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(successful_read);
60990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             : GetDataFrameMinimumSize(),
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            reader->GetBytesConsumed());
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(current_frame_length_,
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            remaining_data_length_ + reader->GetBytesConsumed());
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is just a sanity check for help debugging early frame errors.
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remaining_data_length_ > 1000000u) {
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The strncmp for 5 is safe because we only hit this point if we
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // have kMinCommonHeader (8) bytes
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!syn_frame_processed_ &&
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " request";
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      probable_http_response_ = true;
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Unexpectedly large frame.  " << display_protocol_
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " session is likely corrupt.";
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if we're here, then we have the common header all received.
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_control_frame) {
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (current_frame_flags_ & ~DATA_FLAG_FIN) {
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_->OnDataFrameHeader(current_frame_stream_id_,
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  remaining_data_length_,
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  current_frame_flags_ & DATA_FLAG_FIN);
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (remaining_data_length_ > 0) {
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Empty data frame.
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (current_frame_flags_ & DATA_FLAG_FIN) {
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          visitor_->OnStreamFrameData(
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              current_frame_stream_id_, NULL, 0, true);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHANGE_STATE(SPDY_AUTO_RESET);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (version != spdy_version_) {
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We check version before we check validity: version can never be
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // 'invalid', it can only be unsupported.
655a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "Unsupported SPDY version " << version
656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << " (expected " << spdy_version_ << ")";
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    set_error(SPDY_UNSUPPORTED_VERSION);
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ProcessControlFrameHeader(control_frame_type_field);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_NO_ERROR, error_code_);
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (control_frame_type_field < FIRST_CONTROL_TYPE ||
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      control_frame_type_field > LAST_CONTROL_TYPE) {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_error(SPDY_INVALID_CONTROL_FRAME);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_type_ == NOOP) {
678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "NOOP control frame found. Ignoring.";
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Do some sanity checking on the control frame sizes and flags.
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (current_frame_type_) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_STREAM:
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetSynStreamMinimumSize()) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ &
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_REPLY:
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetSynReplyMinimumSize()) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RST_STREAM:
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ != GetRstStreamSize()) {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ != 0) {
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS:
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make sure that we have an integral number of 8-byte key/value pairs,
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // plus a 4-byte length field.
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetSettingsMinimumSize() ||
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DLOG(WARNING) << "Invalid length for SETTINGS frame: "
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      << current_frame_length_;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ &
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case PING:
721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (current_frame_length_ != GetPingSize()) {
722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME);
723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      } else if (current_frame_flags_ != 0) {
724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GOAWAY:
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (current_frame_length_ != GetGoAwaySize()) {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME);
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else if (current_frame_flags_ != 0) {
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HEADERS:
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetHeadersMinimumSize()) {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_UPDATE:
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ != GetWindowUpdateSize()) {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ != 0) {
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CREDENTIAL:
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetCredentialMinimumSize()) {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ != 0) {
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case BLOCKED:
758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (current_frame_length_ != GetBlockedSize()) {
759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      } else if (current_frame_flags_ != 0) {
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
7647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case PUSH_PROMISE:
7657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (current_frame_length_ < GetPushPromiseMinimumSize()) {
7667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME);
7677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      } else if (current_frame_flags_ != 0) {
7687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
7697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
7707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Valid " << display_protocol_
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " control frame with unhandled type: "
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << current_frame_type_;
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // This branch should be unreachable because of the frame type bounds
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // check above. However, we DLOG(FATAL) here in an effort to painfully
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // club the head of the developer who failed to keep this file in sync
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // with spdy_protocol.h.
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(FATAL);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_INVALID_CONTROL_FRAME);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == SPDY_ERROR) {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Received control frame with way too big of a payload: "
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  << current_frame_length_;
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_type_ == CREDENTIAL) {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the frame size without variable-length data.
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 frame_size_without_variable_data;
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (current_frame_type_) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_STREAM:
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syn_frame_processed_ = true;
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame_size_without_variable_data = GetSynStreamMinimumSize();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_REPLY:
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syn_frame_processed_ = true;
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame_size_without_variable_data = GetSynReplyMinimumSize();
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS:
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame_size_without_variable_data = GetSettingsMinimumSize();
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
814ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case HEADERS:
815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      frame_size_without_variable_data = GetHeadersMinimumSize();
816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
8177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case PUSH_PROMISE:
8187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      frame_size_without_variable_data = GetPushPromiseMinimumSize();
8197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_size_without_variable_data = -1;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((frame_size_without_variable_data == -1) &&
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (current_frame_length_ > kControlFrameBufferSize)) {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should already be in an error state. Double-check.
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(SPDY_ERROR, state_);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state_ != SPDY_ERROR) {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(DFATAL) << display_protocol_
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  << " control frame buffer too small for fixed-length frame.";
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_size_without_variable_data > 0) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have a control frame with a header block. We need to parse the
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // remainder of the control frame's header before we can parse the header
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // block. The start of the header block varies with the control type.
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GE(frame_size_without_variable_data,
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              static_cast<int32>(current_frame_buffer_length_));
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remaining_control_header_ = frame_size_without_variable_data -
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        current_frame_buffer_length_;
8457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            size_t max_bytes) {
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_to_read = std::min(*len, max_bytes);
856868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (bytes_to_read > 0) {
857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_GE(kControlFrameBufferSize,
858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              current_frame_buffer_length_ + bytes_to_read);
859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           *data,
861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           bytes_to_read);
862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_frame_buffer_length_ += bytes_to_read;
863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *data += bytes_to_read;
864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *len -= bytes_to_read;
865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bytes_to_read;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSerializedLength(const int spdy_version,
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const SpdyHeaderBlock* headers) {
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t num_name_value_pairs_size
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t length_of_name_size = num_name_value_pairs_size;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t length_of_value_size = num_name_value_pairs_size;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t total_length = num_name_value_pairs_size;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (SpdyHeaderBlock::const_iterator it = headers->begin();
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != headers->end();
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We add space for the length of the name and the length of the value as
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // well as the length of the name and the length of the value.
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_length += length_of_name_size + it->first.size() +
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    length_of_value_size + it->second.size();
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return total_length;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const int spdy_version,
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const SpdyHeaderBlock* headers) {
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (spdy_version < 3) {
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->WriteUInt16(headers->size());  // Number of headers.
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->WriteUInt32(headers->size());  // Number of headers.
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyHeaderBlock::const_iterator it;
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = headers->begin(); it != headers->end(); ++it) {
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (spdy_version < 3) {
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteString(it->first);
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteString(it->second);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteStringPiece32(it->first);
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteStringPiece32(it->second);
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Clean up after we no longer need
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to workaround http://crbug.com/139744.
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(USE_SYSTEM_ZLIB)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These constants are used by zlib to differentiate between normal data and
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data. Cookie data is handled specially by zlib when compressing.
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ZDataClass {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kZStandardData is compressed normally, save that it will never match
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // against any other class of data in the window.
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kZStandardData = Z_CLASS_STANDARD,
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kZCookieData is compressed in its own Huffman blocks and only matches in
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // its entirety and only against other kZCookieData blocks. Any matches must
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prefix matches.
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kZCookieData = Z_CLASS_COOKIE,
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // against the window.
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needed when switching between classes of data.
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteZ(const base::StringPiece& data,
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ZDataClass clas,
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   z_stream* out) {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we are switching from standard to non-standard data then we need to end
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the current Huffman context to avoid it leaking between them.
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (out->clas == kZStandardData &&
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clas != kZStandardData) {
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->avail_in = 0;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = deflate(out, Z_PARTIAL_FLUSH);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(Z_OK, rv);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(0u, out->avail_in);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(0u, out->avail_out);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->avail_in = data.size();
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->clas = clas;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (clas == kZStandardData) {
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = deflate(out, Z_NO_FLUSH);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = deflate(out, Z_PARTIAL_FLUSH);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data.empty()) {
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If we didn't provide any data then zlib will return Z_BUF_ERROR.
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(Z_OK, rv);
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0u, out->avail_in);
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(0u, out->avail_out);
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteLengthZ(size_t n,
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         unsigned length,
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ZDataClass clas,
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         z_stream* out) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[4];
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(length, sizeof(buf));
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 1; i <= length; i++) {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf[length - i] = n;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n >>= 8;
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteZ(base::StringPiece(buf, length), clas, out);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// manner that resists the length of the compressed data from compromising
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data.
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     z_stream* z) const {
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned length_length = 4;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (spdy_version_ < 3)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    length_length = 2;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteLengthZ(headers->size(), length_length, kZStandardData, z);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, std::string>::const_iterator it;
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = headers->begin(); it != headers->end(); ++it) {
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteZ(it->first, kZStandardData, z);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->first == "cookie") {
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We require the cookie values (save for the last) to end with a
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // semicolon and (save for the first) to start with a space. This is
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // typically the format that we are given them in but we reserialize them
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to be sure.
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<base::StringPiece> cookie_values;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t cookie_length = 0;
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPiece cookie_data(it->second);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (;;) {
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (!cookie_data.empty() &&
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_data.remove_prefix(1);
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (cookie_data.empty())
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t i;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < cookie_data.size(); i++) {
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (cookie_data[i] == ';')
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (i < cookie_data.size()) {
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_values.push_back(cookie_data.substr(0, i));
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_length += i + 2 /* semicolon and space */;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_data.remove_prefix(i + 1);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_values.push_back(cookie_data);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_length += cookie_data.size();
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_data.remove_prefix(i);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteLengthZ(cookie_length, length_length, kZStandardData, z);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < cookie_values.size(); i++) {
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string cookie;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Since zlib will only back-reference complete cookies, a cookie that
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // is currently last (and so doesn't have a trailing semicolon) won't
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // match if it's later in a non-final position. The same is true of
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the first cookie.
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (i == 0 && cookie_values.size() == 1) {
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = cookie_values[i].as_string();
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (i == 0) {
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = cookie_values[i].as_string() + ";";
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (i < cookie_values.size() - 1) {
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = " " + cookie_values[i].as_string() + ";";
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = " " + cookie_values[i].as_string();
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WriteZ(cookie, kZCookieData, z);
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (it->first == "accept" ||
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "accept-charset" ||
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "accept-encoding" ||
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "accept-language" ||
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "host" ||
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "version" ||
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "method" ||
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "scheme" ||
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":host" ||
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":version" ||
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":method" ||
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":scheme" ||
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "user-agent") {
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteZ(it->second, kZStandardData, z);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Non-whitelisted headers are Huffman compressed in their own block, but
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // don't match against the window.
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteZ(it->second, kZHuffmanOnlyData, z);
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z->avail_in = 0;
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = deflate(z, Z_SYNC_FLUSH);
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(Z_OK, rv);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z->clas = kZStandardData;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(USE_SYSTEM_ZLIB)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        size_t len) {
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remaining_control_header_ > 0) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 remaining_control_header_);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remaining_control_header_ -= bytes_read;
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ -= bytes_read;
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remaining_control_header_ == 0) {
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyFrameReader reader(current_frame_buffer_.get(),
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           current_frame_buffer_length_);
10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (current_frame_type_) {
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SYN_STREAM:
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
109590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          bool successful_read = true;
109690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          if (spdy_version_ < 4) {
109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
109890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            DCHECK(successful_read);
109990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          }
1100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (current_frame_stream_id_ == 0) {
1101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpdyStreamId associated_to_stream_id = kInvalidStream;
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          successful_read = reader.ReadUInt31(&associated_to_stream_id);
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(successful_read);
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpdyPriority priority = 0;
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          successful_read = reader.ReadUInt8(&priority);
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(successful_read);
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (protocol_version() < 3) {
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            priority = priority >> 6;
11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          } else {
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            priority = priority >> 5;
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          uint8 slot = 0;
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (protocol_version() < 3) {
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // SPDY 2 had an unused byte here. Seek past it.
11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            reader.Seek(1);
11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          } else {
11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            successful_read = reader.ReadUInt8(&slot);
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DCHECK(successful_read);
11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(reader.IsDoneReading());
11287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (debug_visitor_) {
11297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            debug_visitor_->OnReceiveCompressedFrame(
11307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_stream_id_,
11317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_type_,
11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_length_);
11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->OnSynStream(
11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              current_frame_stream_id_,
11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              associated_to_stream_id,
11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              priority,
11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              slot,
11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case SETTINGS:
1145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        visitor_->OnSettings(current_frame_flags_ &
1146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                             SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
11487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        break;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SYN_REPLY:
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case HEADERS:
11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // SYN_REPLY and HEADERS are the same, save for the visitor call.
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
115390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          bool successful_read = true;
115490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          if (spdy_version_ < 4) {
115590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
115690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            DCHECK(successful_read);
115790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          }
1158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (current_frame_stream_id_ == 0) {
1159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
11622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (protocol_version() < 3) {
11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // SPDY 2 had two unused bytes here. Seek past them.
11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            reader.Seek(2);
11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(reader.IsDoneReading());
11677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (debug_visitor_) {
11687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            debug_visitor_->OnReceiveCompressedFrame(
11697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_stream_id_,
11707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_type_,
11717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_length_);
11727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (current_frame_type_ == SYN_REPLY) {
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            visitor_->OnSynReply(
11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                current_frame_stream_id_,
11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          } else {
11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            visitor_->OnHeaders(
11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                current_frame_stream_id_,
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case PUSH_PROMISE:
1186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        {
1187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK_LE(4, protocol_version());
1188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (current_frame_stream_id_ == 0) {
1189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          SpdyStreamId promised_stream_id = kInvalidStream;
1193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          bool successful_read = reader.ReadUInt31(&promised_stream_id);
1194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(successful_read);
1195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(reader.IsDoneReading());
1196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (promised_stream_id == 0) {
1197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (debug_visitor_) {
1201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            debug_visitor_->OnReceiveCompressedFrame(
1202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                current_frame_stream_id_,
1203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                current_frame_type_,
1204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                current_frame_length_);
1205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          visitor_->OnPushPromise(current_frame_stream_id_, promised_stream_id);
1207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
1208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(false);
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not buffer the control payload. Instead, either passes directly to the
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// visitor or decompresses and then passes directly to the visitor, via
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDeliverControlFrameHeaderData() or
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDecompressControlFrameHeaderData() respectively.
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  size_t data_len) {
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool processed_successfully = true;
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_type_ != SYN_STREAM &&
12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_frame_type_ != SYN_REPLY &&
1228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      current_frame_type_ != HEADERS &&
1229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      current_frame_type_ != PUSH_PROMISE) {
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t process_bytes = std::min(data_len, remaining_data_length_);
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (process_bytes > 0) {
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enable_compression_) {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processed_successfully = IncrementallyDecompressControlFrameHeaderData(
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_frame_stream_id_, data, process_bytes);
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processed_successfully = IncrementallyDeliverControlFrameHeaderData(
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_frame_stream_id_, data, process_bytes);
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ -= process_bytes;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle the case that there is no futher data in this frame.
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remaining_data_length_ == 0 && processed_successfully) {
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The complete header block has been delivered. We send a zero-length
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // OnControlFrameHeaderData() to indicate this.
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If this is a FIN, tell the caller.
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (current_frame_flags_ & CONTROL_FLAG_FIN) {
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle error.
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!processed_successfully) {
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data_len;
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return amount processed.
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process_bytes;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               size_t data_len) {
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(SETTINGS, current_frame_type_);
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t processed_bytes = 0;
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loop over our incoming data.
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (unprocessed_bytes > 0) {
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Process up to one setting at a time.
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t processing = std::min(
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unprocessed_bytes,
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<size_t>(8 - settings_scratch_.setting_buf_len));
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if we have a complete setting in our input.
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (processing == 8) {
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Parse the setting directly out of the input without buffering.
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!ProcessSetting(data + processed_bytes)) {
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return processed_bytes;
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Continue updating settings_scratch_.setting_buf.
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             data + processed_bytes,
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             processing);
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings_scratch_.setting_buf_len += processing;
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Check if we have a complete setting buffered.
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (settings_scratch_.setting_buf_len == 8) {
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ProcessSetting(settings_scratch_.setting_buf)) {
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME);
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return processed_bytes;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Reset settings_scratch_.setting_buf for our next setting.
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        settings_scratch_.setting_buf_len = 0;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Iterate.
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unprocessed_bytes -= processing;
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    processed_bytes += processing;
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we're done handling this SETTINGS frame.
13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remaining_data_length_ -= processed_bytes;
13142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remaining_data_length_ == 0) {
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return processed_bytes;
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::ProcessSetting(const char* data) {
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract fields.
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsFlagsAndId id_and_flags =
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 flags = id_and_flags.flags();
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate id.
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (id_and_flags.id()) {
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS_UPLOAD_BANDWIDTH:
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS_DOWNLOAD_BANDWIDTH:
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS_ROUND_TRIP_TIME:
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS_MAX_CONCURRENT_STREAMS:
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS_CURRENT_CWND:
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS_DOWNLOAD_RETRANS_RATE:
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS_INITIAL_WINDOW_SIZE:
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Valid values.
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Detect duplciates.
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  << " in " << display_protocol_ << " SETTINGS frame "
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  << "(last settikng id was "
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  << settings_scratch_.last_setting_id << ").";
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings_scratch_.last_setting_id = id;
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate flags.
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((flags & ~(kFlagsMask)) != 0) {
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  << flags;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validation succeeded. Pass on to visitor.
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visitor_->OnSetting(id, flags, value);
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
1372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  size_t bytes_read =
1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_);
1374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  remaining_data_length_ -= bytes_read;
1375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (remaining_data_length_ == 0) {
1376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SpdyFrameReader reader(current_frame_buffer_.get(),
1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           current_frame_buffer_length_);
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    reader.Seek(GetControlFrameHeaderSize());  // Skip frame header.
1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Use frame-specific handlers.
1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    switch (current_frame_type_) {
1382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case RST_STREAM: {
1383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          bool successful_read = true;
1384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          if (spdy_version_ < 4) {
1385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DCHECK(successful_read);
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
1388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          SpdyRstStreamStatus status = RST_STREAM_INVALID;
1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          uint32 status_raw = status;
1390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          successful_read = reader.ReadUInt32(&status_raw);
1391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          DCHECK(successful_read);
1392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          if (status_raw > RST_STREAM_INVALID &&
1393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              status_raw < RST_STREAM_NUM_STATUS_CODES) {
1394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            status = static_cast<SpdyRstStreamStatus>(status_raw);
1395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          } else {
1396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            // TODO(hkhalil): Probably best to OnError here, depending on
1397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            // our interpretation of the spec. Keeping with existing liberal
1398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            // behavior for now.
1399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          }
1400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          DCHECK(reader.IsDoneReading());
1401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          visitor_->OnRstStream(current_frame_stream_id_, status);
1402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
1403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
1404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case PING: {
1405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          SpdyPingId id = 0;
1406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          bool successful_read = reader.ReadUInt32(&id);
1407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(successful_read);
1408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(reader.IsDoneReading());
1409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          visitor_->OnPing(id);
1410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
1411ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        break;
1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case GOAWAY: {
1413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          DCHECK(successful_read);
1415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          SpdyGoAwayStatus status = GOAWAY_OK;
1416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          if (spdy_version_ >= 3) {
1417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            uint32 status_raw = GOAWAY_OK;
14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            successful_read = reader.ReadUInt32(&status_raw);
14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DCHECK(successful_read);
1420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            if (status_raw >= GOAWAY_OK &&
1421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) {
1422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              status = static_cast<SpdyGoAwayStatus>(status_raw);
14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            } else {
14242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              // TODO(hkhalil): Probably best to OnError here, depending on
14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              // our interpretation of the spec. Keeping with existing liberal
14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              // behavior for now.
14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          DCHECK(reader.IsDoneReading());
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          visitor_->OnGoAway(current_frame_stream_id_, status);
1431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
1433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case WINDOW_UPDATE: {
1434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          uint32 delta_window_size = 0;
1435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          bool successful_read = true;
1436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (spdy_version_ < 4) {
1437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            DCHECK(successful_read);
1439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          successful_read = reader.ReadUInt32(&delta_window_size);
1441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(successful_read);
1442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(reader.IsDoneReading());
1443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          visitor_->OnWindowUpdate(current_frame_stream_id_,
1444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                   delta_window_size);
1445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
1446ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        break;
1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case BLOCKED: {
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          DCHECK_LE(4, protocol_version());
1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          DCHECK(reader.IsDoneReading());
1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          visitor_->OnBlocked(current_frame_stream_id_);
1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default:
1454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // Unreachable.
1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessCredentialFramePayload(const char* data, size_t len) {
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len > 0) {
1465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Clamp to the actual remaining payload.
1466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (len > remaining_data_length_) {
1467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      len = remaining_data_length_;
1468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool processed_succesfully = visitor_->OnCredentialFrameData(data, len);
14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ -= len;
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!processed_succesfully) {
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_CREDENTIAL_FRAME_CORRUPT);
14732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (remaining_data_length_ == 0) {
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_->OnCredentialFrameData(NULL, 0);
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHANGE_STATE(SPDY_AUTO_RESET);
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return len;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remaining_data_length_ > 0) {
14852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t amount_to_forward = std::min(remaining_data_length_, len);
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Only inform the visitor if there is data.
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (amount_to_forward) {
14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        visitor_->OnStreamFrameData(
14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            current_frame_stream_id_, data, amount_to_forward, false);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data += amount_to_forward;
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= amount_to_forward;
14952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ -= amount_to_forward;
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the FIN flag is set, and there is no more data in this data
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // frame, inform the visitor of EOF via a 0-length data frame.
14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remaining_data_length_ == 0) {
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          size_t header_length,
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          SpdyHeaderBlock* block) const {
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyFrameReader reader(header_data, header_length);
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read number of headers.
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 num_headers;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (spdy_version_ < 3) {
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16 temp;
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reader.ReadUInt16(&temp)) {
1520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read number of headers.";
15212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_headers = temp;
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reader.ReadUInt32(&num_headers)) {
1526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read number of headers.";
15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read each header.
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32 index = 0; index < num_headers; ++index) {
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece temp;
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read header name.
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            : !reader.ReadStringPiece32(&temp)) {
1538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
1539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << num_headers << ").";
15402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = temp.as_string();
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read header value.
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            : !reader.ReadStringPiece32(&temp)) {
1547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
1548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << num_headers << ").";
15492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = temp.as_string();
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure no duplicates.
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (block->find(name) != block->end()) {
1555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
1556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << num_headers << ").";
15572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Store header.
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*block)[name] = value;
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return reader.GetBytesConsumed();
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::ParseCredentialData(const char* data, size_t len,
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     SpdyCredential* credential) {
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(credential);
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyFrameReader parser(data, len);
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece temp;
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parser.ReadUInt16(&credential->slot)) {
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parser.ReadStringPiece32(&temp)) {
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  credential->proof = temp.as_string();
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!parser.IsDoneReading()) {
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!parser.ReadStringPiece32(&temp)) {
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    credential->certs.push_back(temp.as_string());
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1591ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdyFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
1592ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                       const char* data,
1593ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                       uint32 len, SpdyDataFlags flags) const {
1594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK_EQ(0, flags & (!DATA_FLAG_FIN));
1595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1596ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
1597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data_ir.set_fin(flags & DATA_FLAG_FIN);
1598ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return SerializeData(data_ir);
1599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1600ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
1602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const size_t kSize = GetDataFrameMinimumSize() + data.data().length();
1603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1604ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyDataFlags flags = DATA_FLAG_NONE;
1605ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (data.fin()) {
1606ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    flags = DATA_FLAG_FIN;
1607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1608ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyFrameBuilder builder(kSize);
1610ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  builder.WriteBytes(data.data().data(), data.data().length());
1612ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK_EQ(kSize, builder.length());
1613ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return builder.take();
1614ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1615ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1616ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
1617ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const SpdyDataIR& data) const {
1618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const size_t kSize = GetDataFrameMinimumSize();
1619ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1620ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyDataFlags flags = DATA_FLAG_NONE;
1621ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (data.fin()) {
1622ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    flags = DATA_FLAG_FIN;
1623ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1624ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1625ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SpdyFrameBuilder builder(kSize);
1626ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1627ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (protocol_version() < 4) {
1628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    builder.OverwriteLength(*this, data.data().length());
1629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  } else {
1630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    builder.OverwriteLength(*this, data.data().length() + kSize);
1631ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1632ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK_EQ(kSize, builder.length());
1633ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return builder.take();
1634ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
16362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateSynStream(
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyStreamId stream_id,
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyStreamId associated_stream_id,
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyPriority priority,
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 credential_slot,
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyControlFlags flags,
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SpdyHeaderBlock* headers) {
16432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL);
16442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdySynStreamIR syn_stream(stream_id);
16462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syn_stream.set_associated_to_stream_id(associated_stream_id);
16472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syn_stream.set_priority(priority);
16482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syn_stream.set_slot(credential_slot);
16492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
16502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
16512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(hkhalil): Avoid copy here.
16522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *(syn_stream.GetMutableNameValueBlock()) = *headers;
16532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return SerializeSynStream(syn_stream);
16552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynStream(
16582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdySynStreamIR& syn_stream) {
16592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
16602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (syn_stream.fin()) {
16612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_FIN;
16622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
16632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (syn_stream.unidirectional()) {
16642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_UNIDIRECTIONAL;
16652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
16662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size of this frame, including variable-length name-value block.
16682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t size = GetSynStreamMinimumSize()
16692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      + GetSerializedLength(syn_stream.name_value_block());
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(size);
167290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
167390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
167490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(syn_stream.stream_id());
167590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
167690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this,
167790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             SYN_STREAM,
167890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             flags,
167990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             syn_stream.stream_id());
168090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
16812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(syn_stream.associated_to_stream_id());
16822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 priority = syn_stream.priority();
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (priority > GetLowestPriority()) {
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(DFATAL) << "Priority out-of-bounds.";
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    priority = GetLowestPriority();
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
16882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt8(syn_stream.slot());
16892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
16902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SerializeNameValueBlock(&builder, syn_stream);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (debug_visitor_) {
16937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const size_t payload_len = GetSerializedLength(
16947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        protocol_version(), &(syn_stream.name_value_block()));
16957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
16967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          SYN_STREAM,
16977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          payload_len,
16987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          builder.length());
16997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
17007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
17012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateSynReply(
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyStreamId stream_id,
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyControlFlags flags,
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SpdyHeaderBlock* headers) {
17082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN);
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdySynReplyIR syn_reply(stream_id);
17112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
17122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(hkhalil): Avoid copy here.
17132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *(syn_reply.GetMutableNameValueBlock()) = *headers;
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return SerializeSynReply(syn_reply);
17162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynReply(
17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdySynReplyIR& syn_reply) {
17202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (syn_reply.fin()) {
17222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_FIN;
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size of this frame, including variable-length name-value block.
17262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = GetSynReplyMinimumSize()
17272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      + GetSerializedLength(syn_reply.name_value_block());
17282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(size);
173090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
173190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
173290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(syn_reply.stream_id());
173390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
173490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this,
173590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             SYN_REPLY,
173690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             flags,
173790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             syn_reply.stream_id());
173890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (protocol_version() < 3) {
17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteUInt16(0);  // Unused.
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SerializeNameValueBlock(&builder, syn_reply);
17442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (debug_visitor_) {
17467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const size_t payload_len = GetSerializedLength(
17477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        protocol_version(), &(syn_reply.name_value_block()));
17487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
17497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          SYN_REPLY,
17507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          payload_len,
17517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          builder.length());
17527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
17537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
17542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateRstStream(
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyStreamId stream_id,
17592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyRstStreamStatus status) const {
17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyRstStreamIR rst_stream(stream_id, status);
17612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SerializeRstStream(rst_stream);
17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeRstStream(
17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyRstStreamIR& rst_stream) const {
17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(GetRstStreamSize());
176790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
176890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
176990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(rst_stream.stream_id());
177090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
177190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this,
177290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             RST_STREAM,
177390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             0,
177490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             rst_stream.stream_id());
177590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(rst_stream.status());
17772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetRstStreamSize(), builder.length());
17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
17792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateSettings(
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SettingsMap& values) const {
17832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdySettingsIR settings;
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (SettingsMap::const_iterator it = values.begin();
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != values.end();
17862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
17872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    settings.AddSetting(it->first,
17882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        it->second.second);
17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SerializeSettings(settings);
17932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSettings(
17962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdySettingsIR& settings) const {
17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
17982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (settings.clear_settings()) {
17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SpdySettingsIR::ValueMap* values = &(settings.values());
18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of this SETTINGS frame.
18042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t size = GetSettingsMinimumSize() + (values->size() * 8);
18052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(size);
180790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
180890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, SETTINGS, flags);
180990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
181090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this, SETTINGS, flags, 0);
181190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(values->size());
18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != values->end();
18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint8 setting_flags = 0;
18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it->second.persist_value) {
18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it->second.persisted) {
18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      setting_flags |= SETTINGS_FLAG_PERSISTED;
18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SettingsFlagsAndId flags_and_id(setting_flags, it->first);
18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteBytes(&id_and_flags_wire, 4);
18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteUInt32(it->second.value);
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(size, builder.length());
18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
1834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_LE(4, protocol_version());
1835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SpdyFrameBuilder builder(GetBlockedSize());
1836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id());
1837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return builder.take();
1838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const {
18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyPingIR ping(unique_id);
18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SerializePing(ping);
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
18462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(GetPingSize());
184790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
184890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, PING, kNoFlags);
184990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
185090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this, PING, 0, 0);
185190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(ping.id());
18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetPingSize(), builder.length());
18542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateGoAway(
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyStreamId last_accepted_stream_id,
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyGoAwayStatus status) const {
18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyGoAwayIR goaway(last_accepted_stream_id, status);
18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SerializeGoAway(goaway);
18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeGoAway(
18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyGoAwayIR& goaway) const {
18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(GetGoAwaySize());
186790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
186890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
186990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
187090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this, GOAWAY, 0, 0);
187190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(goaway.last_good_stream_id());
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (protocol_version() >= 3) {
18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteUInt32(goaway.status());
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetGoAwaySize(), builder.length());
18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateHeaders(
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyStreamId stream_id,
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyControlFlags flags,
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyHeaderBlock* header_block) {
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Basically the same as CreateSynReply().
18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN));
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyHeadersIR headers(stream_id);
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  headers.set_fin(flags & CONTROL_FLAG_FIN);
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(hkhalil): Avoid copy here.
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *(headers.GetMutableNameValueBlock()) = *header_block;
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return SerializeHeaders(headers);
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeHeaders(
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyHeadersIR& headers) {
18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (headers.fin()) {
18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_FIN;
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size of this frame, including variable-length name-value block.
19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = GetHeadersMinimumSize()
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      + GetSerializedLength(headers.name_value_block());
19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(size);
190790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
190890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, HEADERS, flags);
190990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(headers.stream_id());
191090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
191190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this,
191290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             HEADERS,
191390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             flags,
191490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             headers.stream_id());
191590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (protocol_version() < 3) {
19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteUInt16(0);  // Unused.
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SerializeNameValueBlock(&builder, headers);
19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (debug_visitor_) {
19247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const size_t payload_len = GetSerializedLength(
19257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        protocol_version(), &(headers.name_value_block()));
19267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
19277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          HEADERS,
19287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          payload_len,
19297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          builder.length());
19307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
19317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateWindowUpdate(
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyStreamId stream_id,
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 delta_window_size) const {
19382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyWindowUpdateIR window_update(stream_id, delta_window_size);
19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SerializeWindowUpdate(window_update);
19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyWindowUpdateIR& window_update) const {
19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(GetWindowUpdateSize());
194590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
194690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
194790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(window_update.stream_id());
194890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
194990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this,
195090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             WINDOW_UPDATE,
195190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             kNoFlags,
195290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             window_update.stream_id());
195390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(window_update.delta());
19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetWindowUpdateSize(), builder.length());
19562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
19572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(hkhalil): Gut with SpdyCredential removal.
19602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateCredentialFrame(
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SpdyCredential& credential) const {
19622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyCredentialIR credential_ir(credential.slot);
19632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  credential_ir.set_proof(credential.proof);
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<std::string>::const_iterator cert = credential.certs.begin();
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       cert != credential.certs.end();
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++cert) {
19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    credential_ir.AddCertificate(*cert);
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return SerializeCredential(credential_ir);
19702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeCredential(
19732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyCredentialIR& credential) const {
19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t size = GetCredentialMinimumSize();
19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size += 4 + credential.proof().length();  // Room for proof.
19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (SpdyCredentialIR::CertificateList::const_iterator it =
19772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       credential.certificates()->begin();
19782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != credential.certificates()->end();
19792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += 4 + it->length();  // Room for certificate.
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder builder(size);
198490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (spdy_version_ < 4) {
198590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, CREDENTIAL, kNoFlags);
198690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
198790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteFramePrefix(*this, CREDENTIAL, kNoFlags, 0);
198890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
19892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt16(credential.slot());
19902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetCredentialMinimumSize(), builder.length());
19912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteStringPiece32(credential.proof());
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (SpdyCredentialIR::CertificateList::const_iterator it =
19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       credential.certificates()->begin();
19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != credential.certificates()->end();
19952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteStringPiece32(*it);
19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(size, builder.length());
19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20027dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSpdyFrame* SpdyFramer::CreatePushPromise(
20037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SpdyStreamId stream_id,
20047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SpdyStreamId promised_stream_id,
20057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const SpdyHeaderBlock* header_block) {
20067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
20077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // TODO(hkhalil): Avoid copy here.
20087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  *(push_promise.GetMutableNameValueBlock()) = *header_block;
20097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
20107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return SerializePushPromise(push_promise);
20117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
20127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
20137dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSpdyFrame* SpdyFramer::SerializePushPromise(
20147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const SpdyPushPromiseIR& push_promise) {
20157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_LE(4, protocol_version());
20167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The size of this frame, including variable-length name-value block.
20177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  size_t size = GetPushPromiseMinimumSize()
20187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      + GetSerializedLength(push_promise.name_value_block());
20197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
20207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SpdyFrameBuilder builder(size);
20217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  builder.WriteFramePrefix(*this, PUSH_PROMISE, kNoFlags,
20227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           push_promise.stream_id());
20237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  builder.WriteUInt32(push_promise.promised_stream_id());
20247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
20257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
20267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SerializeNameValueBlock(&builder, push_promise);
20277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
20287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (debug_visitor_) {
20297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const size_t payload_len = GetSerializedLength(
20307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        protocol_version(), &(push_promise.name_value_block()));
20317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
20327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        PUSH_PROMISE, payload_len, builder.length());
20337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
20347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
20357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return builder.take();
20367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
20377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
2039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass FrameSerializationVisitor : public SpdyFrameVisitor {
2041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
2042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~FrameSerializationVisitor() {}
2044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2047ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2048ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    frame_.reset(framer_->SerializeData(data));
2049ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
2050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeSynStream(syn_stream));
2052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeSynReply(syn_reply));
2055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeRstStream(rst_stream));
2058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeSettings(settings));
2061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializePing(ping));
2064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeGoAway(goaway));
2067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeHeaders(headers));
2070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitWindowUpdate(
2072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const SpdyWindowUpdateIR& window_update) OVERRIDE {
2073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeWindowUpdate(window_update));
2074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitCredential(const SpdyCredentialIR& credential) OVERRIDE {
2076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeCredential(credential));
2077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeBlocked(blocked));
2080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
20817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void VisitPushPromise(
20827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const SpdyPushPromiseIR& push_promise) OVERRIDE {
20837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    frame_.reset(framer_->SerializePushPromise(push_promise));
20847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
2087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyFramer* framer_;
2088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdySerializedFrame> frame_;
2089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
2090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
2092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FrameSerializationVisitor visitor(this);
2095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  frame.Visit(&visitor);
2096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return visitor.ReleaseSerializedFrame();
2097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
20992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
21002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t uncompressed_length =
21012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetSerializedLength(protocol_version(), &headers);
21022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!enable_compression_) {
21032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return uncompressed_length;
21042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
21052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  z_stream* compressor = GetHeaderCompressor();
21062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since we'll be performing lots of flushes when compressing the data,
21072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // zlib's lower bounds may be insufficient.
21082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 2 * deflateBound(compressor, uncompressed_length);
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following compression setting are based on Brian Olson's analysis. See
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for more details.
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_SYSTEM_ZLIB)
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// System zlib is not expected to have workaround for http://crbug.com/139744,
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so disable compression in that case.
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Remove the special case when it's no longer necessary.
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 0;
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // !defined(USE_SYSTEM_ZLIB)
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 9;
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(USE_SYSTEM_ZLIB)
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorWindowSizeInBits = 11;
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorMemLevel = 1;
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderCompressor() {
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_compressor_.get())
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return header_compressor_.get();  // Already initialized.
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_compressor_.reset(new z_stream);
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(header_compressor_.get(), 0, sizeof(z_stream));
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = deflateInit2(header_compressor_.get(),
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kCompressorLevel,
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             Z_DEFLATED,
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kCompressorWindowSizeInBits,
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kCompressorMemLevel,
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             Z_DEFAULT_STRATEGY);
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success == Z_OK) {
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 : kV3Dictionary;
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    : kV3DictionarySize;
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success = deflateSetDictionary(header_compressor_.get(),
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   reinterpret_cast<const Bytef*>(dictionary),
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   dictionary_size);
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success != Z_OK) {
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "deflateSetDictionary failure: " << success;
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header_compressor_.reset(NULL);
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return header_compressor_.get();
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderDecompressor() {
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_decompressor_.get())
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return header_decompressor_.get();  // Already initialized.
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_decompressor_.reset(new z_stream);
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(header_decompressor_.get(), 0, sizeof(z_stream));
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = inflateInit(header_decompressor_.get());
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success != Z_OK) {
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "inflateInit failure: " << success;
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header_decompressor_.reset(NULL);
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return header_decompressor_.get();
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Incrementally decompress the control frame's header block, feeding the
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// result to the visitor in chunks. Continue this until the visitor
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// indicates that it cannot process any more data, or (more commonly) we
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run out of data to deliver.
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
21762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyStreamId stream_id,
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* data,
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t len) {
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get a decompressor or set error.
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z_stream* decomp = GetHeaderDecompressor();
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (decomp == NULL) {
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_error(SPDY_DECOMPRESS_FAILURE);
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool processed_successfully = true;
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer[kHeaderDataChunkMaxSize];
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomp->avail_in = len;
2192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
2193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // signal an error back in ProcessControlFrameBeforeHeaderBlock.  So if we've
2194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // reached this method successfully, stream_id should be nonzero.
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(0u, stream_id);
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (decomp->avail_in > 0 && processed_successfully) {
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decomp->next_out = reinterpret_cast<Bytef*>(buffer);
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decomp->avail_out = arraysize(buffer);
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = inflate(decomp, Z_SYNC_FLUSH);
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == Z_NEED_DICT) {
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   : kV3Dictionary;
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      : kV3DictionarySize;
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const DictionaryIds& ids = g_dictionary_ids.Get();
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      : ids.v3_dictionary_id;
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Need to try again with the right dictionary.
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (decomp->adler == dictionary_id) {
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = inflateSetDictionary(decomp,
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  reinterpret_cast<const Bytef*>(dictionary),
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  dictionary_size);
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv == Z_OK)
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = inflate(decomp, Z_SYNC_FLUSH);
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Inflate will generate a Z_BUF_ERROR if it runs out of input
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // without producing any output.  The input is consumed and
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffered internally by zlib so we can detect this condition by
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // checking if avail_in is 0 after the call to inflate.
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((rv == Z_OK) || input_exhausted) {
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (decompressed_len > 0) {
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        processed_successfully = visitor_->OnControlFrameHeaderData(
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            stream_id, buffer, decompressed_len);
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!processed_successfully) {
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Assume that the problem was the header block was too large for the
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // visitor.
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(WARNING) << "inflate failure: " << rv << " " << len;
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_DECOMPRESS_FAILURE);
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processed_successfully = false;
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return processed_successfully;
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
22452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyStreamId stream_id, const char* data, size_t len) {
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool read_successfully = true;
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (read_successfully && len > 0) {
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           bytes_to_deliver);
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data += bytes_to_deliver;
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= bytes_to_deliver;
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!read_successfully) {
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Assume that the problem was the header block was too large for the
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // visitor.
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return read_successfully;
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlockWithoutCompression(
22632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyFrameBuilder* builder,
2264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const SpdyNameValueBlock& name_value_block) const {
22652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Serialize number of headers.
22662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (protocol_version() < 3) {
2267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    builder->WriteUInt16(name_value_block.size());
22682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    builder->WriteUInt32(name_value_block.size());
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Serialize each header.
2273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
2274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       it != name_value_block.end();
22752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
22762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (protocol_version() < 3) {
22772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteString(it->first);
22782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteString(it->second);
22792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
22802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteStringPiece32(it->first);
22812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteStringPiece32(it->second);
22822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
22832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlock(
22872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyFrameBuilder* builder,
22882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyFrameWithNameValueBlockIR& frame) {
22892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!enable_compression_) {
2290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SerializeNameValueBlockWithoutCompression(builder,
2291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                     frame.name_value_block());
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // First build an uncompressed version to be fed into the compressor.
22952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t uncompressed_len = GetSerializedLength(
22962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      protocol_version(), &(frame.name_value_block()));
22972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpdyFrameBuilder uncompressed_builder(uncompressed_len);
2298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
2299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            frame.name_value_block());
23002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
23012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  z_stream* compressor = GetHeaderCompressor();
23032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!compressor) {
23042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(DFATAL) << "Could not obtain compressor.";
23052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StatsCounter compressed_frames("spdy.CompressedFrames");
23092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
23102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
23112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create an output frame.
23132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since we'll be performing lots of flushes when compressing the data,
23142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // zlib's lower bounds may be insufficient.
23152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
23162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(akalin): Avoid the duplicate calculation with
23172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSerializedLength(const SpdyHeaderBlock&).
23182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int compressed_max_size =
23192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      2 * deflateBound(compressor, uncompressed_len);
23202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(phajdan.jr): Clean up after we no longer need
23222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to workaround http://crbug.com/139744.
23232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB)
23242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
23252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->avail_in = uncompressed_len;
23262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_SYSTEM_ZLIB)
23272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->next_out = reinterpret_cast<Bytef*>(
23282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->GetWritableBuffer(compressed_max_size));
23292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->avail_out = compressed_max_size;
23302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(phajdan.jr): Clean up after we no longer need
23322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to workaround http://crbug.com/139744.
23332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB)
23342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv = deflate(compressor, Z_SYNC_FLUSH);
23352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != Z_OK) {  // How can we know that it compressed everything?
23362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This shouldn't happen, right?
23372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "deflate failure: " << rv;
23382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(akalin): Upstream this return.
23392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
23402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
23412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
23422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
23432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_SYSTEM_ZLIB)
23442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int compressed_size = compressed_max_size - compressor->avail_out;
23462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder->Seek(compressed_size);
23472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder->RewriteLength(*this);
23482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pre_compress_bytes.Add(uncompressed_len);
23502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  post_compress_bytes.Add(compressed_size);
23512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressed_frames.Increment();
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
2356