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)#include "net/spdy/spdy_framer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/valgrind/memcheck.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_builder.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_reader.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_bitmasks.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/zlib.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using base::StringPiece;
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using std::string;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Compute the id of our dictionary so that we know we're using the
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// right one when asked for it.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uLong CalculateDictionaryId(const char* dictionary,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const size_t dictionary_size) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uLong initial_value = adler32(0L, Z_NULL, 0);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return adler32(initial_value,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 reinterpret_cast<const Bytef*>(dictionary),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 dictionary_size);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Check to see if the name and value of a cookie are both empty.
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool IsCookieEmpty(const base::StringPiece& cookie) {
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (cookie.size() == 0) {
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     return true;
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t pos = cookie.find('=');
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (pos  == base::StringPiece::npos) {
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     return false;
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Ignore leading whitespaces of cookie value.
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t value_start = pos + 1;
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (; value_start < cookie.size(); value_start++) {
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     if (!(cookie[value_start] == ' ' || cookie[value_start] == '\t')) {
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)     }
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (pos == 0) && ((cookie.size() - value_start) == 0);
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DictionaryIds {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryIds()
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uLong v2_dictionary_id;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uLong v3_dictionary_id;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adler ID for the SPDY header compressor dictionaries. Note that they are
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialized lazily to avoid static initializers.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to indicate no flags in a SPDY flags field.
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8 kNoFlags = 0;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Wire sizes of priority payloads.
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kPriorityDependencyPayloadSize = 4;
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kPriorityWeightPayloadSize = 1;
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// The size of the control frame buffer. Must be >= the minimum size of the
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// calculation details.
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const size_t SpdyFramer::kControlFrameBufferSize = 19;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_SPDY_STATE_CHANGES
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate)                                  \
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {                                                          \
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "Changing state from: "                         \
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << StateToString(state_)                           \
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << " to " << StateToString(newstate) << "\n";      \
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ != SPDY_ERROR);                               \
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(previous_state_, state_);                         \
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;                                   \
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = newstate;                                          \
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate)                                  \
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {                                                          \
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ != SPDY_ERROR);                               \
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(previous_state_, state_);                         \
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;                                   \
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = newstate;                                          \
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SpdyMajorVersion version, uint32 wire) {
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (version < SPDY3) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertFlagsAndIdForSpdy2(&wire);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : flags_(flags), id_(id & 0x00ffffff) {
1134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuuint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version)
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (version < SPDY3) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertFlagsAndIdForSpdy2(&wire);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return wire;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is used to preserve buggy behavior and works on both
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// little-endian and big-endian hosts.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as vice versa).
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8* wire_array = reinterpret_cast<uint8*>(val);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(wire_array[0], wire_array[3]);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(wire_array[1], wire_array[2]);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                   size_t len) {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char* rst_stream_data,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_t len) {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SpdyFramer::SpdyFramer(SpdyMajorVersion version)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : current_frame_buffer_(new char[kControlFrameBufferSize]),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enable_compression_(true),
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_(NULL),
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      debug_visitor_(NULL),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_protocol_("SPDY"),
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spdy_version_(version),
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syn_frame_processed_(false),
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      probable_http_response_(false),
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      expect_continuation_(0),
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      end_stream_when_done_(false) {
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Reset();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::~SpdyFramer() {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_compressor_.get()) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deflateEnd(header_compressor_.get());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_decompressor_.get()) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inflateEnd(header_decompressor_.get());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::Reset() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = SPDY_RESET;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  previous_state_ = SPDY_RESET;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_code_ = SPDY_NO_ERROR;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remaining_data_length_ = 0;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remaining_control_header_ = 0;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_buffer_length_ = 0;
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  current_frame_type_ = DATA;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_flags_ = 0;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_length_ = 0;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_frame_stream_id_ = kInvalidStream;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings_scratch_.Reset();
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  altsvc_scratch_.Reset();
1884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  remaining_padding_payload_length_ = 0;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMinimumSize() const {
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Size, in bytes, of the control frame header.
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetControlFrameHeaderSize() const {
1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynStreamMinimumSize() const {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of a SYN_STREAM frame not including the variable-length
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // name-value block.
2034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // control frame header + 2 * 4 (stream IDs) + 1 (priority)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // + 1 (unused, was credential slot)
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 10;
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return GetControlFrameHeaderSize() +
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        kPriorityDependencyPayloadSize +
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        kPriorityWeightPayloadSize;
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynReplyMinimumSize() const {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of a SYN_REPLY frame not including the variable-length
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // name-value block.
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t size = GetControlFrameHeaderSize();
2194ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream IDs)
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += 4;
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In SPDY 2, there were 2 unused bytes before payload.
2264ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() < SPDY3) {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += 2;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return size;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::GetRstStreamMinimumSize() const {
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Size, in bytes, of a RST_STREAM frame.
2354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream id) + 4 (status code)
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 8;
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // frame prefix + 4 (status code)
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 4;
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSettingsMinimumSize() const {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of a SETTINGS frame not including the IDs and values
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // from the variable-length value block. Calculated as:
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // control frame header + 4 (number of ID/value pairs)
2504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return GetControlFrameHeaderSize() + 4;
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return GetControlFrameHeaderSize();
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetPingSize() const {
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Size, in bytes, of this PING frame.
2594ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Calculated as:
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // control frame header + 4 (id)
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return GetControlFrameHeaderSize() + 4;
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Calculated as:
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // control frame header + 8 (id)
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return GetControlFrameHeaderSize() + 8;
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::GetGoAwayMinimumSize() const {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of this GOAWAY frame. Calculated as:
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // 1. Control frame header size
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t size = GetControlFrameHeaderSize();
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // 2. Last good stream id (4 bytes)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size += 4;
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (protocol_version() >= SPDY3) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += 4;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return size;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetHeadersMinimumSize() const  {
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Size, in bytes, of a HEADERS frame not including the variable-length
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // name-value block.
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t size = GetControlFrameHeaderSize();
2904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream IDs)
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += 4;
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // In SPDY 2, there were 2 unused bytes before payload.
2974ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY2) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size += 2;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return size;
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetWindowUpdateSize() const {
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Size, in bytes, of a WINDOW_UPDATE frame.
3064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // control frame header + 4 (stream id) + 4 (delta)
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 8;
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Calculated as:
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // frame prefix + 4 (delta)
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetControlFrameHeaderSize() + 4;
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t SpdyFramer::GetBlockedSize() const {
3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_LT(SPDY3, protocol_version());
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Size, in bytes, of a BLOCKED frame.
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The BLOCKED frame has no payload beyond the control frame header.
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return GetControlFrameHeaderSize();
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsize_t SpdyFramer::GetPushPromiseMinimumSize() const {
3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_LT(SPDY3, protocol_version());
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Calculated as frame prefix + 4 (promised stream id).
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return GetControlFrameHeaderSize() + 4;
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::GetContinuationMinimumSize() const {
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Size, in bytes, of a CONTINUATION frame not including the variable-length
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // headers fragments.
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetControlFrameHeaderSize();
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::GetAltSvcMinimumSize() const {
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // (optional) Origin fields, all of which can vary in length.
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Note that this gives a lower bound on the frame size rather than a true
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // minimum; the actual frame should always be larger than this.
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // + 1 (pid_len) + 1 (host_len).
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return GetControlFrameHeaderSize() + 9;
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::GetPrioritySize() const {
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Size, in bytes, of a PRIORITY frame.
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return GetControlFrameHeaderSize() +
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      kPriorityDependencyPayloadSize +
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      kPriorityWeightPayloadSize;
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMinimumSize() const {
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMaximumSize() const {
3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return SpdyConstants::GetFrameMaximumSize(protocol_version());
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMaximumPayload() const {
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetFrameMaximumSize() - GetDataFrameMinimumSize();
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return SpdyConstants::GetPrefixLength(type, protocol_version());
3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StateToString(int state) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_ERROR:
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "ERROR";
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_AUTO_RESET:
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "AUTO_RESET";
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_RESET:
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "RESET";
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_READING_COMMON_HEADER:
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_COMMON_HEADER";
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_FRAME_PAYLOAD:
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CONTROL_FRAME_PAYLOAD";
3824ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    case SPDY_READ_PADDING_LENGTH:
3834ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      return "SPDY_READ_PADDING_LENGTH";
3844ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    case SPDY_CONSUME_PADDING:
3854ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      return "SPDY_CONSUME_PADDING";
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_IGNORE_REMAINING_PAYLOAD:
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "IGNORE_REMAINING_PAYLOAD";
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_FORWARD_STREAM_FRAME:
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FORWARD_STREAM_FRAME";
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_FRAME_HEADER_BLOCK:
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case SPDY_GOAWAY_FRAME_PAYLOAD:
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "SPDY_GOAWAY_FRAME_PAYLOAD";
3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case SPDY_RST_STREAM_FRAME_PAYLOAD:
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "SPDY_RST_STREAM_FRAME_PAYLOAD";
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_SETTINGS_FRAME_PAYLOAD:
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_SETTINGS_FRAME_PAYLOAD";
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SPDY_ALTSVC_FRAME_PAYLOAD:
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return "SPDY_ALTSVC_FRAME_PAYLOAD";
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_STATE";
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::set_error(SpdyError error) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(visitor_);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_code_ = error;
409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // These values will usually get reset once we come to the end
410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // of a header block, but if we run into an error that
411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // might not happen, so reset them here.
412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  expect_continuation_ = 0;
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  end_stream_when_done_ = false;
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHANGE_STATE(SPDY_ERROR);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visitor_->OnError(this);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::ErrorCodeToString(int error_code) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (error_code) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_NO_ERROR:
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "NO_ERROR";
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_INVALID_CONTROL_FRAME:
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_CONTROL_FRAME";
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CONTROL_PAYLOAD_TOO_LARGE";
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_ZLIB_INIT_FAILURE:
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "ZLIB_INIT_FAILURE";
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_UNSUPPORTED_VERSION:
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNSUPPORTED_VERSION";
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_DECOMPRESS_FAILURE:
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "DECOMPRESS_FAILURE";
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_COMPRESS_FAILURE:
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "COMPRESS_FAILURE";
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SPDY_INVALID_DATA_FRAME_FLAGS:
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SPDY_INVALID_DATA_FRAME_FLAGS";
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SPDY_INVALID_CONTROL_FRAME_FLAGS:
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case SPDY_UNEXPECTED_FRAME:
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "UNEXPECTED_FRAME";
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_ERROR";
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StatusCodeToString(int status_code) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (status_code) {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INVALID:
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID";
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_PROTOCOL_ERROR:
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "PROTOCOL_ERROR";
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INVALID_STREAM:
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_STREAM";
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_REFUSED_STREAM:
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "REFUSED_STREAM";
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_UNSUPPORTED_VERSION:
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNSUPPORTED_VERSION";
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_CANCEL:
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CANCEL";
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INTERNAL_ERROR:
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INTERNAL_ERROR";
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_FLOW_CONTROL_ERROR:
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FLOW_CONTROL_ERROR";
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_STREAM_IN_USE:
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "STREAM_IN_USE";
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_STREAM_ALREADY_CLOSED:
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "STREAM_ALREADY_CLOSED";
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_INVALID_CREDENTIALS:
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_CREDENTIALS";
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case RST_STREAM_FRAME_TOO_LARGE:
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FRAME_TOO_LARGE";
4715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case RST_STREAM_CONNECT_ERROR:
4725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return "CONNECT_ERROR";
4735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case RST_STREAM_ENHANCE_YOUR_CALM:
4745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return "ENHANCE_YOUR_CALM";
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_STATUS";
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case DATA:
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "DATA";
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_STREAM:
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SYN_STREAM";
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_REPLY:
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SYN_REPLY";
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RST_STREAM:
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "RST_STREAM";
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS:
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "SETTINGS";
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PING:
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "PING";
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GOAWAY:
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "GOAWAY";
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HEADERS:
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "HEADERS";
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_UPDATE:
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "WINDOW_UPDATE";
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CREDENTIAL:
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CREDENTIAL";
5017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case PUSH_PROMISE:
5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return "PUSH_PROMISE";
503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case CONTINUATION:
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "CONTINUATION";
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case PRIORITY:
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return "PRIORITY";
50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case ALTSVC:
50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return "ALTSVC";
50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    case BLOCKED:
51003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return "BLOCKED";
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_CONTROL_TYPE";
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(visitor_);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state_) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_ERROR:
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_AUTO_RESET:
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_RESET:
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Reset();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (len > 0) {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CHANGE_STATE(SPDY_READING_COMMON_HEADER);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_READING_COMMON_HEADER: {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bytes_read = ProcessCommonHeader(data, len);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
5427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // Control frames that contain header blocks
543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
5447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // take a different path through the state machine - they
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // will go:
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   2. SPDY_CONTROL_FRAME_HEADER_BLOCK
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // SETTINGS frames take a slightly modified route:
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   2. SPDY_SETTINGS_FRAME_PAYLOAD
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //  All other control frames will use the alternate route directly to
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //  SPDY_CONTROL_FRAME_PAYLOAD
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_SETTINGS_FRAME_PAYLOAD: {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int bytes_read = ProcessSettingsFramePayload(data, len);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
56923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        int bytes_read = ProcessControlFrameHeaderBlock(
5704ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            data, len, protocol_version() > SPDY3);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case SPDY_RST_STREAM_FRAME_PAYLOAD: {
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        size_t bytes_read = ProcessRstStreamFramePayload(data, len);
5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        len -= bytes_read;
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        data += bytes_read;
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case SPDY_GOAWAY_FRAME_PAYLOAD: {
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        size_t bytes_read = ProcessGoAwayFramePayload(data, len);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case SPDY_ALTSVC_FRAME_PAYLOAD: {
591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        size_t bytes_read = ProcessAltSvcFramePayload(data, len);
592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        len -= bytes_read;
593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        data += bytes_read;
594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_CONTROL_FRAME_PAYLOAD: {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bytes_read = ProcessControlFramePayload(data, len);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      case SPDY_READ_PADDING_LENGTH: {
6054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        size_t bytes_read = ProcessFramePaddingLength(data, len);
6064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        len -= bytes_read;
6074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        data += bytes_read;
6084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        break;
6094ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      }
6104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
6114ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      case SPDY_CONSUME_PADDING: {
6124ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        size_t bytes_read = ProcessFramePadding(data, len);
6134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        len -= bytes_read;
6144ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        data += bytes_read;
6154ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        break;
6164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      }
6174ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
6185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case SPDY_IGNORE_REMAINING_PAYLOAD: {
6195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
6205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        len -= bytes_read;
6215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        data += bytes_read;
6225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        break;
6235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
6245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SPDY_FORWARD_STREAM_FRAME: {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t bytes_read = ProcessDataFramePayload(data, len);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len -= bytes_read;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += bytes_read;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "Invalid value for " << display_protocol_
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << " framer state: " << state_;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This ensures that we don't infinite-loop if state_ gets an
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // invalid value somehow, such as due to a SpdyFramer getting deleted
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // from a callback it calls.
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (state_ != previous_state_);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bottom:
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(len == 0 || state_ == SPDY_ERROR);
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_buffer_length_ == 0 &&
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remaining_data_length_ == 0 &&
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remaining_control_header_ == 0) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "State: " << StateToString(state_);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should only be called when we're in the SPDY_READING_COMMON_HEADER
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // state.
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update current frame buffer as needed.
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t bytes_desired =
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetControlFrameHeaderSize() - current_frame_buffer_length_;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Not enough information to do anything meaningful.
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return original_len - len;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // when processing DATA frames below.
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrameReader> reader(
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new SpdyFrameReader(current_frame_buffer_.get(),
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          current_frame_buffer_length_));
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint16 version = 0;
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_control_frame = false;
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
681116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint16 control_frame_type_field =
682116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SpdyConstants::DataFrameType(protocol_version());
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // ProcessControlFrameHeader() will set current_frame_type_ to the
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // correct value if this is a valid control frame.
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  current_frame_type_ = DATA;
6864ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool successful_read = reader->ReadUInt16(&version);
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_control_frame = (version & kControlFlagMask) != 0;
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    version &= ~kControlFlagMask;  // Only valid for control frames.
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (is_control_frame) {
6925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // We check version before we check validity: version can never be
6935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // 'invalid', it can only be unsupported.
6945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
6955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
6965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
6975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // Version does not match the version the framer was initialized with.
6985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        DVLOG(1) << "Unsupported SPDY version "
6995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 << version
7005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 << " (expected " << protocol_version() << ")";
7015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        set_error(SPDY_UNSUPPORTED_VERSION);
7025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return 0;
7035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      } else {
7045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // Convert version from wire format to SpdyMajorVersion.
7055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        version = SpdyConstants::ParseMajorVersion(version);
7065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // We check control_frame_type_field's validity in
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // ProcessControlFrameHeader().
709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      successful_read = reader->ReadUInt16(&control_frame_type_field);
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reader->Rewind();
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      successful_read = reader->ReadUInt31(&current_frame_stream_id_);
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    successful_read = reader->ReadUInt8(&current_frame_flags_);
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32 length_field = 0;
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    successful_read = reader->ReadUInt24(&length_field);
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ = length_field;
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    version = protocol_version();
72603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    uint32 length_field = 0;
72703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    bool successful_read = reader->ReadUInt24(&length_field);
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
730116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    uint8 control_frame_type_field_uint8 =
731116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SpdyConstants::DataFrameType(protocol_version());
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // We check control_frame_type_field's validity in
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // ProcessControlFrameHeader().
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    control_frame_type_field = control_frame_type_field_uint8;
737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    is_control_frame = (protocol_version() > SPDY3) ?
73803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      control_frame_type_field !=
73903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      SpdyConstants::SerializeFrameType(protocol_version(), DATA) :
74003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      control_frame_type_field != 0;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (is_control_frame) {
7434ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      current_frame_length_ = length_field + GetControlFrameHeaderSize();
7444ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    } else {
7454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      current_frame_length_ = length_field + GetDataFrameMinimumSize();
7464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
7474ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    successful_read = reader->ReadUInt8(&current_frame_flags_);
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(successful_read);
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    successful_read = reader->ReadUInt31(&current_frame_stream_id_);
75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(successful_read);
75390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
755a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
756a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Before we accept a DATA frame, we need to make sure we're not in the
757a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // middle of processing a header block.
7584ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    const bool is_continuation_frame = (control_frame_type_field ==
7594ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
7604ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if ((expect_continuation_ != 0) != is_continuation_frame) {
7614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      if (expect_continuation_ != 0) {
7624ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
7634ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                    << "frame, but instead received frame type "
7644ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                    << control_frame_type_field;
7654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      } else {
7664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
7674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      }
768a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      set_error(SPDY_UNEXPECTED_FRAME);
769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return original_len - len;
770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             : GetDataFrameMinimumSize(),
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            reader->GetBytesConsumed());
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(current_frame_length_,
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            remaining_data_length_ + reader->GetBytesConsumed());
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is just a sanity check for help debugging early frame errors.
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remaining_data_length_ > 1000000u) {
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The strncmp for 5 is safe because we only hit this point if we
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // have kMinCommonHeader (8) bytes
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!syn_frame_processed_ &&
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " request";
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      probable_http_response_ = true;
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Unexpectedly large frame.  " << display_protocol_
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " session is likely corrupt.";
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if we're here, then we have the common header all received.
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_control_frame) {
7954ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (protocol_version() > SPDY3) {
79623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      // Catch bogus tests sending oversized DATA frames.
79723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
79823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          << "DATA frame too large for SPDY >= 4.";
79923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
80023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8014ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    uint8 valid_data_flags = 0;
8024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (protocol_version() > SPDY3) {
803116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      valid_data_flags =
804116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
8054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    } else {
8064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      valid_data_flags = DATA_FLAG_FIN;
8074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
8084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
8094ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (current_frame_flags_ & ~valid_data_flags) {
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_->OnDataFrameHeader(current_frame_stream_id_,
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  remaining_data_length_,
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  current_frame_flags_ & DATA_FLAG_FIN);
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (remaining_data_length_ > 0) {
8164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Empty data frame.
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (current_frame_flags_ & DATA_FLAG_FIN) {
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          visitor_->OnStreamFrameData(
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              current_frame_stream_id_, NULL, 0, true);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHANGE_STATE(SPDY_AUTO_RESET);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ProcessControlFrameHeader(control_frame_type_field);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_NO_ERROR, error_code_);
835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
837116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(mlavan): Either remove credential frames from the code entirely,
838116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // or add them to parsing + serialization methods for SPDY3.
8394ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  // Early detection of deprecated frames that we ignore.
8404ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
8414ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (control_frame_type_field == CREDENTIAL) {
8424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      current_frame_type_ = CREDENTIAL;
8434ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      DCHECK_EQ(SPDY3, protocol_version());
8444ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
8454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
8464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      return;
8474ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (!SpdyConstants::IsValidFrameType(protocol_version(),
8514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                       control_frame_type_field)) {
85203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (protocol_version() <= SPDY3) {
85303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
85403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                    << " (protocol version: " << protocol_version() << ")";
85503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      set_error(SPDY_INVALID_CONTROL_FRAME);
85603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
85703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
85803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // In HTTP2 we ignore unknown frame types for extensibility, as long as
85903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // the rest of the control frame header is valid.
86003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // We rely on the visitor to check validity of current_frame_stream_id_.
86103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_,
86203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                   control_frame_type_field);
86303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if (valid_stream) {
86403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        DVLOG(1) << "Ignoring unknown frame type.";
86503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
86603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      } else {
86703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        // Report an invalid frame error and close the stream if the
86803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        // stream_id is not valid.
86903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        DLOG(WARNING) << "Unknown control frame type "
87003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                      << control_frame_type_field
87103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                      << " received on invalid stream "
87203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                      << current_frame_stream_id_;
87303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
87403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      }
87503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
87603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8794ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
8804ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                                      control_frame_type_field);
8814ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Do some sanity checking on the control frame sizes and flags.
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (current_frame_type_) {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_STREAM:
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetSynStreamMinimumSize()) {
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ &
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_REPLY:
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetSynReplyMinimumSize()) {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RST_STREAM:
9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // For SPDY versions < 4, the header has a fixed length.
9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // For SPDY version 4 and up, the RST_STREAM frame may include optional
9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // opaque data, so we only have a lower limit on the frame size.
9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if ((current_frame_length_ != GetRstStreamMinimumSize() &&
9044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch           protocol_version() <= SPDY3) ||
9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          (current_frame_length_ < GetRstStreamMinimumSize() &&
9064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch           protocol_version() > SPDY3)) {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ != 0) {
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS:
913a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make sure that we have an integral number of 8-byte key/value pairs,
915a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // plus a 4-byte length field in SPDY3 and below.
9164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
917a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Size of each key/value pair in bytes.
918116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ < GetSettingsMinimumSize() ||
920a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          (current_frame_length_ - GetControlFrameHeaderSize())
921a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          % setting_size != values_prefix_size) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DLOG(WARNING) << "Invalid length for SETTINGS frame: "
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      << current_frame_length_;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
9254ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      } else if (protocol_version() <= SPDY3 &&
926a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 current_frame_flags_ &
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
9294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      } else if (protocol_version() > SPDY3 &&
930a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
931a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
9324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      } else if (protocol_version() > SPDY3 &&
933a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 current_frame_flags_ & SETTINGS_FLAG_ACK &&
934a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 current_frame_length_ > GetSettingsMinimumSize()) {
935a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
938a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case PING:
940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (current_frame_length_ != GetPingSize()) {
941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME);
9424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
943a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 (current_frame_flags_ & ~PING_FLAG_ACK)) {
944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
946ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case GOAWAY:
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
9495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // For SPDY version < 4, there are only mandatory fields and the header
9505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // has a fixed length. For SPDY version >= 4, optional opaque data may
9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // be appended to the GOAWAY frame, thus there is only a minimal length
9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // restriction.
9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if ((current_frame_length_ != GetGoAwayMinimumSize() &&
9544ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch             protocol_version() <= SPDY3) ||
9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            (current_frame_length_ < GetGoAwayMinimumSize() &&
9564ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch             protocol_version() > SPDY3)) {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME);
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else if (current_frame_flags_ != 0) {
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HEADERS:
9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      {
9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        size_t min_size = GetHeadersMinimumSize();
9664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        if (protocol_version() > SPDY3 &&
9675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          min_size += 4;
9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (current_frame_length_ < min_size) {
97103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          // TODO(mlavan): check here for HEADERS with no payload?
97203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          // (not allowed in SPDY4)
9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME);
9744ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        } else if (protocol_version() <= SPDY3 &&
9755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   current_frame_flags_ & ~CONTROL_FLAG_FIN) {
9765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
977cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        } else if (protocol_version() > SPDY3 &&
978cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   current_frame_flags_ &
979cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
980cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
981116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         HEADERS_FLAG_PADDED)) {
9825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_UPDATE:
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (current_frame_length_ != GetWindowUpdateSize()) {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (current_frame_flags_ != 0) {
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
993868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case BLOCKED:
994cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (current_frame_length_ != GetBlockedSize() ||
995cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          protocol_version() <= SPDY3) {
996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      } else if (current_frame_flags_ != 0) {
998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
10017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case PUSH_PROMISE:
10027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (current_frame_length_ < GetPushPromiseMinimumSize()) {
10037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME);
10044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
1005a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } else if (protocol_version() > SPDY3 &&
1007cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 current_frame_flags_ &
1008cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
1009116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                       HEADERS_FLAG_PADDED)) {
1010a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1011a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
1012a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
1013a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case CONTINUATION:
10145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (current_frame_length_ < GetContinuationMinimumSize() ||
10155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          protocol_version() <= SPDY3) {
1016a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
1017116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case ALTSVC:
1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (current_frame_length_ <= GetAltSvcMinimumSize()) {
1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } else if (current_frame_flags_ != 0) {
1025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
1027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
1028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case PRIORITY:
1029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (current_frame_length_ != GetPrioritySize() ||
1030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          protocol_version() <= SPDY3) {
1031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
1032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      } else if (current_frame_flags_ != 0) {
10337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
10347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
10357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Valid " << display_protocol_
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " control frame with unhandled type: "
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << current_frame_type_;
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // This branch should be unreachable because of the frame type bounds
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // check above. However, we DLOG(FATAL) here in an effort to painfully
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // club the head of the developer who failed to keep this file in sync
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // with spdy_protocol.h.
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(FATAL);
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_INVALID_CONTROL_FRAME);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == SPDY_ERROR) {
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Received control frame with way too big of a payload: "
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  << current_frame_length_;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (current_frame_type_ == GOAWAY) {
10615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
10625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
10635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
10645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (current_frame_type_ == RST_STREAM) {
10665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (current_frame_type_ == ALTSVC) {
1071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
1073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine the frame size without variable-length data.
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 frame_size_without_variable_data;
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (current_frame_type_) {
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_STREAM:
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syn_frame_processed_ = true;
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame_size_without_variable_data = GetSynStreamMinimumSize();
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SYN_REPLY:
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syn_frame_processed_ = true;
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame_size_without_variable_data = GetSynReplyMinimumSize();
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SETTINGS:
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame_size_without_variable_data = GetSettingsMinimumSize();
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1088ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case HEADERS:
1089ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      frame_size_without_variable_data = GetHeadersMinimumSize();
10904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      if (protocol_version() > SPDY3 &&
10914ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        frame_size_without_variable_data +=
1093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            kPriorityDependencyPayloadSize +
1094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            kPriorityWeightPayloadSize;
10955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1096ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
10977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case PUSH_PROMISE:
10987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      frame_size_without_variable_data = GetPushPromiseMinimumSize();
10997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      break;
1100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case CONTINUATION:
1101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      frame_size_without_variable_data = GetContinuationMinimumSize();
1102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_size_without_variable_data = -1;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((frame_size_without_variable_data == -1) &&
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (current_frame_length_ > kControlFrameBufferSize)) {
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should already be in an error state. Double-check.
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(SPDY_ERROR, state_);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state_ != SPDY_ERROR) {
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(DFATAL) << display_protocol_
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  << " control frame buffer too small for fixed-length frame.";
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_size_without_variable_data > 0) {
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have a control frame with a header block. We need to parse the
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // remainder of the control frame's header before we can parse the header
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // block. The start of the header block varies with the control type.
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GE(frame_size_without_variable_data,
11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              static_cast<int32>(current_frame_buffer_length_));
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remaining_control_header_ = frame_size_without_variable_data -
11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        current_frame_buffer_length_;
11287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            size_t max_bytes) {
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_to_read = std::min(*len, max_bytes);
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (bytes_to_read > 0) {
1140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_GE(kControlFrameBufferSize,
1141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              current_frame_buffer_length_ + bytes_to_read);
1142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           *data,
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           bytes_to_read);
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    current_frame_buffer_length_ += bytes_to_read;
1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *data += bytes_to_read;
1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *len -= bytes_to_read;
1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bytes_to_read;
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::GetSerializedLength(
11535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const SpdyMajorVersion spdy_version,
11545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const SpdyHeaderBlock* headers) {
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t num_name_value_pairs_size
11565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t length_of_name_size = num_name_value_pairs_size;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t length_of_value_size = num_name_value_pairs_size;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
116023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t total_length = num_name_value_pairs_size;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (SpdyHeaderBlock::const_iterator it = headers->begin();
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != headers->end();
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We add space for the length of the name and the length of the value as
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // well as the length of the name and the length of the value.
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_length += length_of_name_size + it->first.size() +
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    length_of_value_size + it->second.size();
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return total_length;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
11735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  const SpdyMajorVersion spdy_version,
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const SpdyHeaderBlock* headers) {
11755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (spdy_version < SPDY3) {
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->WriteUInt16(headers->size());  // Number of headers.
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->WriteUInt32(headers->size());  // Number of headers.
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyHeaderBlock::const_iterator it;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = headers->begin(); it != headers->end(); ++it) {
11825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (spdy_version < SPDY3) {
11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteString(it->first);
11842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteString(it->second);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteStringPiece32(it->first);
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      frame->WriteStringPiece32(it->second);
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Clean up after we no longer need
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to workaround http://crbug.com/139744.
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(USE_SYSTEM_ZLIB)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These constants are used by zlib to differentiate between normal data and
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data. Cookie data is handled specially by zlib when compressing.
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ZDataClass {
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kZStandardData is compressed normally, save that it will never match
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // against any other class of data in the window.
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kZStandardData = Z_CLASS_STANDARD,
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kZCookieData is compressed in its own Huffman blocks and only matches in
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // its entirety and only against other kZCookieData blocks. Any matches must
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prefix matches.
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kZCookieData = Z_CLASS_COOKIE,
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // against the window.
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needed when switching between classes of data.
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteZ(const base::StringPiece& data,
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ZDataClass clas,
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   z_stream* out) {
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we are switching from standard to non-standard data then we need to end
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the current Huffman context to avoid it leaking between them.
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (out->clas == kZStandardData &&
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clas != kZStandardData) {
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->avail_in = 0;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = deflate(out, Z_PARTIAL_FLUSH);
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(Z_OK, rv);
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(0u, out->avail_in);
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(0u, out->avail_out);
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->avail_in = data.size();
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->clas = clas;
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (clas == kZStandardData) {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = deflate(out, Z_NO_FLUSH);
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = deflate(out, Z_PARTIAL_FLUSH);
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!data.empty()) {
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If we didn't provide any data then zlib will return Z_BUF_ERROR.
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(Z_OK, rv);
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(0u, out->avail_in);
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(0u, out->avail_out);
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteLengthZ(size_t n,
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         unsigned length,
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ZDataClass clas,
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         z_stream* out) {
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[4];
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(length, sizeof(buf));
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 1; i <= length; i++) {
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf[length - i] = n;
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n >>= 8;
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteZ(base::StringPiece(buf, length), clas, out);
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// manner that resists the length of the compressed data from compromising
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data.
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     z_stream* z) const {
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned length_length = 4;
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (spdy_version_ < 3)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    length_length = 2;
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteLengthZ(headers->size(), length_length, kZStandardData, z);
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, std::string>::const_iterator it;
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (it = headers->begin(); it != headers->end(); ++it) {
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteZ(it->first, kZStandardData, z);
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->first == "cookie") {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We require the cookie values (save for the last) to end with a
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // semicolon and (save for the first) to start with a space. This is
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // typically the format that we are given them in but we reserialize them
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to be sure.
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<base::StringPiece> cookie_values;
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t cookie_length = 0;
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPiece cookie_data(it->second);
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (;;) {
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (!cookie_data.empty() &&
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_data.remove_prefix(1);
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (cookie_data.empty())
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t i;
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = 0; i < cookie_data.size(); i++) {
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (cookie_data[i] == ';')
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (i < cookie_data.size()) {
13015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          if (!IsCookieEmpty(cookie_data.substr(0, i))) {
13025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cookie_values.push_back(cookie_data.substr(0, i));
13035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cookie_length += i + 2 /* semicolon and space */;
13045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          }
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_data.remove_prefix(i + 1);
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
13075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          if (!IsCookieEmpty(cookie_data)) {
13085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cookie_values.push_back(cookie_data);
13095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cookie_length += cookie_data.size();
13105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          } else if (cookie_length > 2) {
13115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            cookie_length -= 2 /* compensate for previously added length */;
13125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          }
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_data.remove_prefix(i);
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteLengthZ(cookie_length, length_length, kZStandardData, z);
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < cookie_values.size(); i++) {
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string cookie;
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Since zlib will only back-reference complete cookies, a cookie that
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // is currently last (and so doesn't have a trailing semicolon) won't
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // match if it's later in a non-final position. The same is true of
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the first cookie.
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (i == 0 && cookie_values.size() == 1) {
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = cookie_values[i].as_string();
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (i == 0) {
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = cookie_values[i].as_string() + ";";
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (i < cookie_values.size() - 1) {
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = " " + cookie_values[i].as_string() + ";";
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie = " " + cookie_values[i].as_string();
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WriteZ(cookie, kZCookieData, z);
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (it->first == "accept" ||
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "accept-charset" ||
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "accept-encoding" ||
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "accept-language" ||
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "host" ||
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "version" ||
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "method" ||
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "scheme" ||
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":host" ||
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":version" ||
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":method" ||
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == ":scheme" ||
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               it->first == "user-agent") {
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteZ(it->second, kZStandardData, z);
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Non-whitelisted headers are Huffman compressed in their own block, but
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // don't match against the window.
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteZ(it->second, kZHuffmanOnlyData, z);
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z->avail_in = 0;
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = deflate(z, Z_SYNC_FLUSH);
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(Z_OK, rv);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z->clas = kZStandardData;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(USE_SYSTEM_ZLIB)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                        size_t len) {
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
13695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const size_t original_len = len;
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remaining_control_header_ > 0) {
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 remaining_control_header_);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remaining_control_header_ -= bytes_read;
13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ -= bytes_read;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remaining_control_header_ == 0) {
13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyFrameReader reader(current_frame_buffer_.get(),
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           current_frame_buffer_length_);
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (current_frame_type_) {
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SYN_STREAM:
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
13864ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          DCHECK_GE(SPDY3, protocol_version());
138790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          bool successful_read = true;
13884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          successful_read = reader.ReadUInt31(&current_frame_stream_id_);
13894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          DCHECK(successful_read);
1390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (current_frame_stream_id_ == 0) {
1391ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1393ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpdyStreamId associated_to_stream_id = kInvalidStream;
13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          successful_read = reader.ReadUInt31(&associated_to_stream_id);
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(successful_read);
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpdyPriority priority = 0;
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          successful_read = reader.ReadUInt8(&priority);
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(successful_read);
14024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() <= SPDY2) {
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            priority = priority >> 6;
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          } else {
14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            priority = priority >> 5;
14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         // Seek past unused byte; used to be credential slot in SPDY 3.
14095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         reader.Seek(1);
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(reader.IsDoneReading());
14127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (debug_visitor_) {
14137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            debug_visitor_->OnReceiveCompressedFrame(
14147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_stream_id_,
14157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_type_,
14167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_length_);
14177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->OnSynStream(
14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              current_frame_stream_id_,
14202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              associated_to_stream_id,
14212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              priority,
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case SETTINGS:
14284ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        if (protocol_version() > SPDY3 &&
14294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            current_frame_flags_ & SETTINGS_FLAG_ACK) {
1430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          visitor_->OnSettingsAck();
1431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          CHANGE_STATE(SPDY_AUTO_RESET);
1432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        } else {
1433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          visitor_->OnSettings(current_frame_flags_ &
1434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
14377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        break;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SYN_REPLY:
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case HEADERS:
14402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // SYN_REPLY and HEADERS are the same, save for the visitor call.
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
14424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() > SPDY3) {
14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            DCHECK_EQ(HEADERS, current_frame_type_);
14445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          }
144590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          bool successful_read = true;
14464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() <= SPDY3) {
144790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
144890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            DCHECK(successful_read);
144990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          }
1450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (current_frame_stream_id_ == 0) {
1451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
14544ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() <= SPDY2) {
14552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // SPDY 2 had two unused bytes here. Seek past them.
14562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            reader.Seek(2);
14572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
14584ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() > SPDY3 &&
1459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             current_frame_type_ == HEADERS) {
1461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            expect_continuation_ = current_frame_stream_id_;
1462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          }
14645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          const bool has_priority =
14655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
14665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          uint32 priority = 0;
14674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() > SPDY3 && has_priority) {
1468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            // TODO(jgraettinger): Process dependency rather than ignoring it.
1469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            reader.Seek(kPriorityDependencyPayloadSize);
1470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            uint8 weight = 0;
1471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            successful_read = reader.ReadUInt8(&weight);
1472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            if (successful_read) {
1473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              priority = MapWeightToPriority(weight);
1474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            }
14755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          }
14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          DCHECK(reader.IsDoneReading());
14777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (debug_visitor_) {
14785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
14795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            SpdyFrameType reported_type = current_frame_type_;
14804ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            if (protocol_version() > SPDY3 && has_priority) {
14815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              reported_type = SYN_STREAM;
14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            }
14837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            debug_visitor_->OnReceiveCompressedFrame(
14847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_stream_id_,
14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                reported_type,
14867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                current_frame_length_);
14877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          }
14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (current_frame_type_ == SYN_REPLY) {
14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            visitor_->OnSynReply(
14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                current_frame_stream_id_,
14912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
14924ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          } else if (protocol_version() > SPDY3 &&
14935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
14945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
14955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            // can be made independent of wire changes.
14965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            visitor_->OnSynStream(
14975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                current_frame_stream_id_,
14985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                0,  // associated_to_stream_id
14995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                priority,
15005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                current_frame_flags_ & CONTROL_FLAG_FIN,
15015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                false);  // unidirectional
15022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          } else {
15032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            visitor_->OnHeaders(
15042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                current_frame_stream_id_,
1505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                expect_continuation_ == 0);
15072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case PUSH_PROMISE:
1512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        {
15134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          DCHECK_LT(SPDY3, protocol_version());
1514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (current_frame_stream_id_ == 0) {
1515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          SpdyStreamId promised_stream_id = kInvalidStream;
1519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          bool successful_read = reader.ReadUInt31(&promised_stream_id);
1520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(successful_read);
1521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(reader.IsDoneReading());
1522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (promised_stream_id == 0) {
1523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            set_error(SPDY_INVALID_CONTROL_FRAME);
1524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            break;
1525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            expect_continuation_ = current_frame_stream_id_;
1528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          }
1529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          if (debug_visitor_) {
1530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            debug_visitor_->OnReceiveCompressedFrame(
1531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                current_frame_stream_id_,
1532ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                current_frame_type_,
1533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                current_frame_length_);
1534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          visitor_->OnPushPromise(current_frame_stream_id_,
1536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  promised_stream_id,
1537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  (current_frame_flags_ &
1538a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
1540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        break;
1542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      case CONTINUATION:
1543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        {
1544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          // Check to make sure the stream id of the current frame is
1545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          // the same as that of the preceding frame.
1546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          // If we're at this point we should already know that
1547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          // expect_continuation_ != 0, so this doubles as a check
1548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          // that current_frame_stream_id != 0.
1549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          if (current_frame_stream_id_ != expect_continuation_) {
1550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            set_error(SPDY_INVALID_CONTROL_FRAME);
1551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            break;
1552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          }
1553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            expect_continuation_ = 0;
1555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          }
1556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          if (debug_visitor_) {
1557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            debug_visitor_->OnReceiveCompressedFrame(
1558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                current_frame_stream_id_,
1559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                current_frame_type_,
1560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                current_frame_length_);
1561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          }
1562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          visitor_->OnContinuation(current_frame_stream_id_,
1563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   (current_frame_flags_ &
1564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    HEADERS_FLAG_END_HEADERS) != 0);
1565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
1566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(false);
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not buffer the control payload. Instead, either passes directly to the
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// visitor or decompresses and then passes directly to the visitor, via
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDeliverControlFrameHeaderData() or
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDecompressControlFrameHeaderData() respectively.
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
158023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                  size_t data_len,
158123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                  bool is_hpack_header_block) {
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool processed_successfully = true;
15852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_frame_type_ != SYN_STREAM &&
15862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_frame_type_ != SYN_REPLY &&
1587ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      current_frame_type_ != HEADERS &&
1588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      current_frame_type_ != PUSH_PROMISE &&
1589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      current_frame_type_ != CONTINUATION) {
15902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
15912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t process_bytes = std::min(
1593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      data_len, remaining_data_length_ - remaining_padding_payload_length_);
159423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (is_hpack_header_block) {
1595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            current_frame_stream_id_, data, process_bytes)) {
159723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      // TODO(jgraettinger): Finer-grained HPACK error codes.
159823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      set_error(SPDY_DECOMPRESS_FAILURE);
159923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      processed_successfully = false;
160023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
160123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else if (process_bytes > 0) {
16024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (enable_compression_ && protocol_version() <= SPDY3) {
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processed_successfully = IncrementallyDecompressControlFrameHeaderData(
16042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_frame_stream_id_, data, process_bytes);
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processed_successfully = IncrementallyDeliverControlFrameHeaderData(
16072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_frame_stream_id_, data, process_bytes);
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
161023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  remaining_data_length_ -= process_bytes;
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle the case that there is no futher data in this frame.
1613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (remaining_data_length_ == remaining_padding_payload_length_ &&
1614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      processed_successfully) {
1615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (expect_continuation_ == 0) {
161623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (is_hpack_header_block) {
1617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                current_frame_stream_id_)) {
161923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          set_error(SPDY_DECOMPRESS_FAILURE);
162023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          processed_successfully = false;
162123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        } else {
162223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          // TODO(jgraettinger): To be removed with migration to
162323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
162423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          // block, delivered via reentrant call to
162523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          // ProcessControlFrameHeaderBlock().
162623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          DeliverHpackBlockAsSpdy3Block();
162723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          return process_bytes;
162823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        }
162923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      } else {
163023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        // The complete header block has been delivered. We send a zero-length
163123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        // OnControlFrameHeaderData() to indicate this.
163223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
163323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      }
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (processed_successfully) {
1636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      CHANGE_STATE(SPDY_CONSUME_PADDING);
1637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle error.
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!processed_successfully) {
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data_len;
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return amount processed.
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process_bytes;
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               size_t data_len) {
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
16522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(SETTINGS, current_frame_type_);
16532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t processed_bytes = 0;
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1656116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
1657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loop over our incoming data.
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (unprocessed_bytes > 0) {
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Process up to one setting at a time.
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t processing = std::min(
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unprocessed_bytes,
1663a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len));
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if we have a complete setting in our input.
1666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (processing == setting_size) {
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Parse the setting directly out of the input without buffering.
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!ProcessSetting(data + processed_bytes)) {
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return processed_bytes;
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Continue updating settings_scratch_.setting_buf.
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             data + processed_bytes,
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             processing);
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      settings_scratch_.setting_buf_len += processing;
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Check if we have a complete setting buffered.
1680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (settings_scratch_.setting_buf_len == setting_size) {
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ProcessSetting(settings_scratch_.setting_buf)) {
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME);
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return processed_bytes;
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Reset settings_scratch_.setting_buf for our next setting.
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        settings_scratch_.setting_buf_len = 0;
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Iterate.
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unprocessed_bytes -= processing;
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    processed_bytes += processing;
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if we're done handling this SETTINGS frame.
16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remaining_data_length_ -= processed_bytes;
16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remaining_data_length_ == 0) {
1698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    visitor_->OnSettingsEnd();
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return processed_bytes;
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
17064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  DCHECK_LT(SPDY3, protocol_version());
1707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
170823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
171023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (block.empty()) {
171123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Special-case this to make tests happy.
171223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ProcessControlFrameHeaderBlock(NULL, 0, false);
171323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
171423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
171523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  SpdyFrameBuilder builder(
17165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      GetSerializedLength(protocol_version(), &block),
17175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SPDY3);
171823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
171923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  SerializeNameValueBlockWithoutCompression(&builder, block);
172023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<SpdyFrame> frame(builder.take());
172123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Preserve padding length, and reset it after the re-entrant call.
1723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t remaining_padding = remaining_padding_payload_length_;
1724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  remaining_padding_payload_length_ = 0;
172623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  remaining_data_length_ = frame->size();
1727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
172823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  remaining_padding_payload_length_ = remaining_padding;
1731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  remaining_data_length_ = remaining_padding;
173223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
173323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::ProcessSetting(const char* data) {
17354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  int id_field;
1736a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SpdySettingsIds id;
1737a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint8 flags = 0;
1738a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint32 value;
1739a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract fields.
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
17424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
1743a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1744a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SettingsFlagsAndId id_and_flags =
17454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
17464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    id_field = id_and_flags.id();
1747a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    flags = id_and_flags.flags();
1748a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1749a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
1750116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    id_field = ntohs(*(reinterpret_cast<const uint16*>(data)));
1751116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    value = ntohl(*(reinterpret_cast<const uint32*>(data + 2)));
1752a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate id.
17554ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
17564ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
175703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (protocol_version() <= SPDY3) {
175803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return false;
175903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } else {
176003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // In HTTP2 we ignore unknown settings for extensibility.
176103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return true;
176203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17644ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
1767a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Detect duplicates.
17684ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (id <= settings_scratch_.last_setting_id) {
1769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    << " in " << display_protocol_ << " SETTINGS frame "
1771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    << "(last setting id was "
1772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    << settings_scratch_.last_setting_id << ").";
1773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return false;
1774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    settings_scratch_.last_setting_id = id;
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Validate flags.
1778a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if ((flags & ~(kFlagsMask)) != 0) {
1780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1781a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    << flags;
1782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return false;
1783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validation succeeded. Pass on to visitor.
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visitor_->OnSetting(id, flags, value);
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
17935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
17945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               remaining_data_length_);
1795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  remaining_data_length_ -= bytes_read;
1796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (remaining_data_length_ == 0) {
1797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SpdyFrameReader reader(current_frame_buffer_.get(),
1798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           current_frame_buffer_length_);
1799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    reader.Seek(GetControlFrameHeaderSize());  // Skip frame header.
1800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Use frame-specific handlers.
1802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    switch (current_frame_type_) {
1803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case PING: {
1804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          SpdyPingId id = 0;
18054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          bool is_ack = protocol_version() > SPDY3 &&
18064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch              (current_frame_flags_ & PING_FLAG_ACK);
18075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          bool successful_read = true;
18084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() <= SPDY3) {
18095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            uint32 id32 = 0;
18105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            successful_read = reader.ReadUInt32(&id32);
18115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            id = id32;
18125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          } else {
18135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            successful_read = reader.ReadUInt64(&id);
18145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          }
1815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(successful_read);
1816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(reader.IsDoneReading());
1817a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          visitor_->OnPing(id, is_ack);
1818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
1819ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        break;
1820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case WINDOW_UPDATE: {
1821ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          uint32 delta_window_size = 0;
1822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          bool successful_read = true;
18234ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          if (protocol_version() <= SPDY3) {
1824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            DCHECK(successful_read);
1826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          }
1827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          successful_read = reader.ReadUInt32(&delta_window_size);
1828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(successful_read);
1829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          DCHECK(reader.IsDoneReading());
1830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          visitor_->OnWindowUpdate(current_frame_stream_id_,
1831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                   delta_window_size);
1832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        }
1833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        break;
1834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      case BLOCKED: {
18354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          DCHECK_LT(SPDY3, protocol_version());
1836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          DCHECK(reader.IsDoneReading());
1837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          visitor_->OnBlocked(current_frame_stream_id_);
1838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
1839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
1840cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case PRIORITY: {
1841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DCHECK_LT(SPDY3, protocol_version());
1842116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          uint32 parent_stream_id;
1843116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          uint8 weight;
1844116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          bool exclusive;
1845116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          bool successful_read = true;
1846116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          successful_read = reader.ReadUInt32(&parent_stream_id);
1847116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          DCHECK(successful_read);
1848116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // Exclusivity is indicated by a single bit flag.
1849116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          exclusive = (parent_stream_id >> 31) != 0;
1850116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // Zero out the highest-order bit to get the parent stream id.
1851116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          parent_stream_id &= 0x7fffffff;
1852116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          successful_read = reader.ReadUInt8(&weight);
1853116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          DCHECK(successful_read);
1854cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DCHECK(reader.IsDoneReading());
1855116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          visitor_->OnPriority(
1856116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              current_frame_stream_id_, parent_stream_id, weight, exclusive);
1857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
1858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
1859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default:
1860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // Unreachable.
1861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
18705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len == 0) {
18715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
18725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
18735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Clamp to the actual remaining payload.
18745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len > remaining_data_length_) {
18755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    len = remaining_data_length_;
18765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
18775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t original_len = len;
18785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check if we had already read enough bytes to parse the GOAWAY header.
18805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const size_t header_size = GetGoAwayMinimumSize();
18815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t unread_header_bytes = header_size - current_frame_buffer_length_;
18825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool already_parsed_header = (unread_header_bytes == 0);
18835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!already_parsed_header) {
18845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Buffer the new GOAWAY header bytes we got.
18855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
18865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Do we have enough to parse the constant size GOAWAY header?
18885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (current_frame_buffer_length_ == header_size) {
18895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Parse out the last good stream id.
18905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdyFrameReader reader(current_frame_buffer_.get(),
18915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             current_frame_buffer_length_);
18925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
18935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
18945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(successful_read);
18955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // In SPDYv3 and up, frames also specify a status code - parse it out.
18975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdyGoAwayStatus status = GOAWAY_OK;
18984ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      if (protocol_version() >= SPDY3) {
18995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        uint32 status_raw = GOAWAY_OK;
19005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        successful_read = reader.ReadUInt32(&status_raw);
19015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(successful_read);
19025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
19035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                               status_raw)) {
19045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
19055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                    status_raw);
19065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        } else {
19075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          if (protocol_version() > SPDY3) {
190803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            // Treat unrecognized status codes as INTERNAL_ERROR as
190903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            // recommended by the HTTP/2 spec.
191003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            status = GOAWAY_INTERNAL_ERROR;
19115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          }
19125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
19135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
19145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Finished parsing the GOAWAY header, call frame handler.
19155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      visitor_->OnGoAway(current_frame_stream_id_, status);
1916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
19175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Handle remaining data as opaque.
19205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool processed_successfully = true;
19215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len > 0) {
19225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    processed_successfully = visitor_->OnGoAwayFrameData(data, len);
19235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  remaining_data_length_ -= original_len;
19255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!processed_successfully) {
19265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    set_error(SPDY_GOAWAY_FRAME_CORRUPT);
19275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (remaining_data_length_ == 0) {
19285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Signal that there is not more opaque data.
19295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    visitor_->OnGoAwayFrameData(NULL, 0);
19305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
19315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return original_len;
19335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
19345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
19365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len == 0) {
19375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
19385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Clamp to the actual remaining payload.
19405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len > remaining_data_length_) {
19415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    len = remaining_data_length_;
19425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t original_len = len;
19445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check if we had already read enough bytes to parse the fixed-length portion
19465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // of the RST_STREAM frame.
19475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const size_t header_size = GetRstStreamMinimumSize();
19485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t unread_header_bytes = header_size - current_frame_buffer_length_;
19495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool already_parsed_header = (unread_header_bytes == 0);
19505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!already_parsed_header) {
19515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Buffer the new RST_STREAM header bytes we got.
19525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
19535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Do we have enough to parse the constant size RST_STREAM header?
19555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (current_frame_buffer_length_ == header_size) {
19565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Parse out the last good stream id.
19575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdyFrameReader reader(current_frame_buffer_.get(),
19585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             current_frame_buffer_length_);
19595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
19604ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      if (protocol_version() <= SPDY3) {
19615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
19625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(successful_read);
19635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
19645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SpdyRstStreamStatus status = RST_STREAM_INVALID;
19665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      uint32 status_raw = status;
19675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bool successful_read = reader.ReadUInt32(&status_raw);
19685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(successful_read);
19695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
19705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                status_raw)) {
19715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        status = static_cast<SpdyRstStreamStatus>(status_raw);
19725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
19735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (protocol_version() > SPDY3) {
197403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          // Treat unrecognized status codes as INTERNAL_ERROR as
197503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          // recommended by the HTTP/2 spec.
197603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          status = RST_STREAM_INTERNAL_ERROR;
19775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        }
19785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
19795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Finished parsing the RST_STREAM header, call frame handler.
19805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      visitor_->OnRstStream(current_frame_stream_id_, status);
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
19845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Handle remaining data as opaque.
19855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool processed_successfully = true;
19865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len > 0) {
19875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    processed_successfully = visitor_->OnRstStreamFrameData(data, len);
19885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  remaining_data_length_ -= original_len;
19905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!processed_successfully) {
19915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
19925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (remaining_data_length_ == 0) {
19935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Signal that there is not more opaque data.
19945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    visitor_->OnRstStreamFrameData(NULL, 0);
19955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
19965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
19975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return original_len;
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2000cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
2001cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (len == 0) {
2002cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
2003cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2004cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2005cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Clamp to the actual remaining payload.
2006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  len = std::min(len, remaining_data_length_);
2007cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2008cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t processed_bytes = 0;
2009cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t processing = 0;
2010cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t bytes_remaining;
2011cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  char* buffer;
2012cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t* buffer_len;
2013cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2014cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (len > 0) {
2015cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (altsvc_scratch_.pid_len == 0) {
2016cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // The size of the frame up to the PID_LEN field.
2017cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      size_t fixed_len_portion = GetAltSvcMinimumSize() - 1;
2018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bytes_remaining = fixed_len_portion - current_frame_buffer_length_;
2019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      processing = std::min(len, bytes_remaining);
2020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Buffer the new ALTSVC bytes we got.
2021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      UpdateCurrentFrameBuffer(&data, &len, processing);
2022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Do we have enough to parse the length of the protocol id?
2024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (current_frame_buffer_length_ == fixed_len_portion) {
2025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // Parse out the max age, port, and pid_len.
2026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        SpdyFrameReader reader(current_frame_buffer_.get(),
2027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               current_frame_buffer_length_);
2028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
2029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age);
2030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        reader.ReadUInt16(&altsvc_scratch_.port);
2031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        reader.Seek(1);  // Reserved byte.
2032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        successful_read = successful_read &&
2033cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          reader.ReadUInt8(&altsvc_scratch_.pid_len);
2034cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        DCHECK(successful_read);
2035cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // Sanity check length value.
2036cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >=
2037cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            current_frame_length_) {
2038cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          set_error(SPDY_INVALID_CONTROL_FRAME);
2039cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return 0;
2040cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
2041cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        altsvc_scratch_.protocol_id.reset(
2042cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            new char[size_t(altsvc_scratch_.pid_len)]);
2043cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
2044cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      processed_bytes += processing;
2045cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
2046cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) {
2047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Buffer protocol id field as in comes in.
2048cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      buffer = altsvc_scratch_.protocol_id.get();
2049cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      buffer_len = &altsvc_scratch_.pid_buf_len;
2050cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len;
2051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else if (altsvc_scratch_.host_len == 0) {
2052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Parse out the host length.
2053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      processing = 1;
2054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data);
2055cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Sanity check length value.
2056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len +
2057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          altsvc_scratch_.host_len > current_frame_length_) {
2058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
2059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return 0;
2060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
2061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]);
2062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Once we have host length, we can also determine the origin length
2063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // by process of elimination.
2064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      altsvc_scratch_.origin_len = current_frame_length_ -
2065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GetAltSvcMinimumSize() -
2066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        altsvc_scratch_.pid_len -
2067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        altsvc_scratch_.host_len;
2068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (altsvc_scratch_.origin_len > 0) {
2069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]);
2070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
2071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      data += processing;
2072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      processed_bytes += processing;
2073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      len -= processing;
2074cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
2075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) {
2076cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Buffer host field as it comes in.
2077cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // TODO(mlavan): check formatting for host and origin
2078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      buffer = altsvc_scratch_.host.get();
2079cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      buffer_len = &altsvc_scratch_.host_buf_len;
2080cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len;
2081cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
2082cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Buffer (optional) origin field as it comes in.
2083cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (altsvc_scratch_.origin_len <= 0) {
2084cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
2085cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return 0;
2086cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
2087cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      buffer = altsvc_scratch_.origin.get();
2088cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      buffer_len = &altsvc_scratch_.origin_buf_len;
2089cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bytes_remaining = remaining_data_length_ -
2090cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        processed_bytes -
2091cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        altsvc_scratch_.origin_buf_len;
2092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (len > bytes_remaining) {
2093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // This is our last field; there shouldn't be any more bytes.
2094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        set_error(SPDY_INVALID_CONTROL_FRAME);
2095cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return 0;
2096cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
2097cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
2098cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2099cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Copy data bytes into the appropriate field.
2100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    processing = std::min(len, bytes_remaining);
2101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    memcpy(buffer + *buffer_len,
2102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           data,
2103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           processing);
2104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *buffer_len += processing;
2105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    data += processing;
2106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    processed_bytes += processing;
2107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    len -= processing;
2108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  remaining_data_length_ -= processed_bytes;
2111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (remaining_data_length_ == 0) {
2112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    visitor_->OnAltSvc(current_frame_stream_id_,
2113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       altsvc_scratch_.max_age,
2114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       altsvc_scratch_.port,
2115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       StringPiece(altsvc_scratch_.protocol_id.get(),
2116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   altsvc_scratch_.pid_len),
2117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       StringPiece(altsvc_scratch_.host.get(),
2118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   altsvc_scratch_.host_len),
2119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       StringPiece(altsvc_scratch_.origin.get(),
2120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   altsvc_scratch_.origin_len));
2121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CHANGE_STATE(SPDY_AUTO_RESET);
2122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return processed_bytes;
2125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
2126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// TODO(raullenchai): ProcessFramePaddingLength should be able to deal with
2128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// HEADERS_FLAG_PADDED and PUSH_PROMISE_FLAG_PADDED as well (see b/15777051).
21294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochsize_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
21304ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_);
2131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(remaining_padding_payload_length_, 0u);
21324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t original_len = len;
2134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (current_frame_flags_ & DATA_FLAG_PADDED) {
2135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (len != 0) {
2136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (remaining_data_length_ < 1) {
2137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return 0;
2139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
2140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data);
2142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ++data;
2143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      --len;
2144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      --remaining_data_length_;
2145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
2146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // We don't have the data available for parsing the pad length field. Keep
2147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // waiting.
21484ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      return 0;
21494ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
21504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (remaining_padding_payload_length_ > remaining_data_length_) {
2153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return 0;
21554ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
2156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (current_frame_type_ == DATA) {
2157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
2159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(current_frame_type_ == HEADERS ||
2160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           current_frame_type_ == PUSH_PROMISE ||
2161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           current_frame_type_ == SYN_STREAM ||
2162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           current_frame_type_ == SYN_REPLY)
2163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        << current_frame_type_;
2164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
21654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
21664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  return original_len - len;
21674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
21684ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
21694ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochsize_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
21704ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
21714ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
21724ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  size_t original_len = len;
21734ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (remaining_padding_payload_length_ > 0) {
21744ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
21754ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (current_frame_type_ == DATA && amount_to_discard > 0) {
2177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // The visitor needs to know about padding so it can send window updates.
2178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Communicate the padding to the visitor through a NULL data pointer,
2179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // with a nonzero size.
21804ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      visitor_->OnStreamFrameData(
21814ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          current_frame_stream_id_, NULL, amount_to_discard, false);
21824ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
21834ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    data += amount_to_discard;
21844ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    len -= amount_to_discard;
21854ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    remaining_padding_payload_length_ -= amount_to_discard;
21864ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    remaining_data_length_ -= amount_to_discard;
21875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
21884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
21895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (remaining_data_length_ == 0) {
2190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If the FIN flag is set, or this ends a header block which set FIN,
21915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // inform the visitor of EOF via a 0-length data frame.
2192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (expect_continuation_ == 0 &&
2193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         end_stream_when_done_)) {
2195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      end_stream_when_done_ = false;
21964ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
21974ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
21984ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    CHANGE_STATE(SPDY_AUTO_RESET);
21994ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
22004ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  return original_len - len;
22014ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
22024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
22034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochsize_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
22044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  size_t original_len = len;
22054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
22064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    size_t amount_to_forward = std::min(
22074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        remaining_data_length_ - remaining_padding_payload_length_, len);
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Only inform the visitor if there is data.
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (amount_to_forward) {
22112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        visitor_->OnStreamFrameData(
22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            current_frame_stream_id_, data, amount_to_forward, false);
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data += amount_to_forward;
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= amount_to_forward;
22172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remaining_data_length_ -= amount_to_forward;
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22204ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (remaining_data_length_ == remaining_padding_payload_length_) {
22214ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    CHANGE_STATE(SPDY_CONSUME_PADDING);
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_len - len;
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
22275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                     size_t len) {
22285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  size_t original_len = len;
22295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (remaining_data_length_ > 0) {
22305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    size_t amount_to_ignore = std::min(remaining_data_length_, len);
22315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    len -= amount_to_ignore;
22325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    remaining_data_length_ -= amount_to_ignore;
22335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
22345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (remaining_data_length_ == 0) {
22365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHANGE_STATE(SPDY_AUTO_RESET);
22375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
22385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return original_len - len;
22395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
22405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          size_t header_length,
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          SpdyHeaderBlock* block) const {
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyFrameReader reader(header_data, header_length);
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read number of headers.
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 num_headers;
22484ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY2) {
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16 temp;
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reader.ReadUInt16(&temp)) {
2251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read number of headers.";
22522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_headers = temp;
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reader.ReadUInt32(&num_headers)) {
2257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read number of headers.";
22582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read each header.
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32 index = 0; index < num_headers; ++index) {
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece temp;
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read header name.
22674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            : !reader.ReadStringPiece32(&temp)) {
2269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << num_headers << ").";
22712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = temp.as_string();
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read header value.
22764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            : !reader.ReadStringPiece32(&temp)) {
2278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << num_headers << ").";
22802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = temp.as_string();
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure no duplicates.
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (block->find(name) != block->end()) {
2286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << num_headers << ").";
22882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Store header.
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*block)[name] = value;
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return reader.GetBytesConsumed();
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSpdySerializedFrame* SpdyFramer::SerializeData(
22985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const SpdyDataIR& data_ir) const {
22994ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  uint8 flags = DATA_FLAG_NONE;
23005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (data_ir.fin()) {
2301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    flags = DATA_FLAG_FIN;
2302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
2303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
23044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3) {
23054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    int num_padding_fields = 0;
2306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (data_ir.padded()) {
2307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      flags |= DATA_FLAG_PADDED;
23084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      ++num_padding_fields;
23094ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
23104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
23114ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    const size_t size_with_padding = num_padding_fields +
23125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        data_ir.data().length() + data_ir.padding_payload_len() +
23134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        GetDataFrameMinimumSize();
23145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SpdyFrameBuilder builder(size_with_padding, protocol_version());
23155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (data_ir.padded()) {
23175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
23184ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
23195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
23205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (data_ir.padding_payload_len() > 0) {
23215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      string padding = string(data_ir.padding_payload_len(), '0');
23224ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      builder.WriteBytes(padding.data(), padding.length());
23234ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
23244ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    DCHECK_EQ(size_with_padding, builder.length());
23254ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    return builder.take();
23264ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  } else {
23275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
23285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SpdyFrameBuilder builder(size, protocol_version());
23295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
23305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
23314ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    DCHECK_EQ(size, builder.length());
23324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    return builder.take();
23334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
2334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
2335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
23365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
23375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const SpdyDataIR& data_ir) const {
23384ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  uint8 flags = DATA_FLAG_NONE;
23395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (data_ir.fin()) {
2340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    flags = DATA_FLAG_FIN;
2341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
23425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  size_t frame_size = GetDataFrameMinimumSize();
23445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  size_t num_padding_fields = 0;
23454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3) {
2346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (data_ir.padded()) {
2347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      flags |= DATA_FLAG_PADDED;
23485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ++num_padding_fields;
23494ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
23505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    frame_size += num_padding_fields;
23514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
2352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
23535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(frame_size, protocol_version());
23545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
23555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (protocol_version() > SPDY3) {
2356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (data_ir.padded()) {
23575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
23585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
23595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.OverwriteLength(*this,  num_padding_fields +
23605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        data_ir.data().length() + data_ir.padding_payload_len());
23615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
23625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.OverwriteLength(*this, data_ir.data().length());
23635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
23645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_EQ(frame_size, builder.length());
2365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return builder.take();
2366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
2367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
23682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynStream(
23692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdySynStreamIR& syn_stream) {
2370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_GE(SPDY3, protocol_version());
23712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
23722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (syn_stream.fin()) {
23732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_FIN;
23742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
23752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (syn_stream.unidirectional()) {
23765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(hkhalil): invalid for HTTP2.
23772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_UNIDIRECTIONAL;
23782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
23795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
23805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sanitize priority.
23815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint8 priority = syn_stream.priority();
23825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (priority > GetLowestPriority()) {
23835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DLOG(DFATAL) << "Priority out-of-bounds.";
23845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    priority = GetLowestPriority();
23855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
23862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size of this frame, including variable-length name-value block.
2388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t size = GetSynStreamMinimumSize() +
2389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetSerializedLength(syn_stream.name_value_block());
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(size, protocol_version());
2392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.WriteUInt32(syn_stream.stream_id());
2394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.WriteUInt32(syn_stream.associated_to_stream_id());
2395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.WriteUInt8(0);  // Unused byte where credential slot used to be.
23972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SerializeNameValueBlock(&builder, syn_stream);
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (debug_visitor_) {
2401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const size_t payload_len =
240223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        GetSerializedLength(protocol_version(),
240323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                            &(syn_stream.name_value_block()));
24047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
24057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          SYN_STREAM,
24067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          payload_len,
24077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          builder.length());
24087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
24097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
24102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynReply(
24142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdySynReplyIR& syn_reply) {
2415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_GE(SPDY3, protocol_version());
24162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
24172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (syn_reply.fin()) {
24182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_FIN;
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size of this frame, including variable-length name-value block.
2422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const size_t size = GetSynReplyMinimumSize() +
2423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                      GetSerializedLength(syn_reply.name_value_block());
24242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(size, protocol_version());
24264ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
242790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
242890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(syn_reply.stream_id());
242990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
24305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.BeginNewFrame(*this,
24315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          HEADERS,
24325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          flags,
24335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          syn_reply.stream_id());
243490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
24354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() < SPDY3) {
24362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteUInt16(0);  // Unused.
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SerializeNameValueBlock(&builder, syn_reply);
24402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (debug_visitor_) {
2442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const size_t payload_len = GetSerializedLength(
2443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        protocol_version(), &(syn_reply.name_value_block()));
24447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
24457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          SYN_REPLY,
24467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          payload_len,
24477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          builder.length());
24487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
24497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeRstStream(
24542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyRstStreamIR& rst_stream) const {
24555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
24565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
24575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // which doesn't currently include RST_STREAM payloads. GFE flags have been
24585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // commented but left in place to simplify future patching.
24595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Compute the output buffer size, taking opaque data into account.
24605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint16 expected_length = GetRstStreamMinimumSize();
24614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3) {
24625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expected_length += rst_stream.description().size();
24635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
24645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(expected_length, protocol_version());
24655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Serialize the RST_STREAM frame.
24674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
246890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
246990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(rst_stream.stream_id());
247090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
24715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
247290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
24735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(rst_stream.status());
24752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
24774ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
24785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    builder.WriteBytes(rst_stream.description().data(),
24795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       rst_stream.description().size());
24802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
24815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
24825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(expected_length, builder.length());
24835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return builder.take();
24842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
24852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSettings(
24872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdySettingsIR& settings) const {
24882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
2489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
2491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (settings.clear_settings()) {
2492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
2494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
2495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (settings.is_ack()) {
2496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      flags |= SETTINGS_FLAG_ACK;
2497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
24982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
24992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SpdySettingsIR::ValueMap* values = &(settings.values());
25002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
25022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Size, in bytes, of this SETTINGS frame.
2503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const size_t size = GetSettingsMinimumSize() +
2504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      (values->size() * setting_size);
25055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(size, protocol_version());
25064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
250790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, SETTINGS, flags);
250890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
25095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.BeginNewFrame(*this, SETTINGS, flags, 0);
251090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If this is an ACK, payload should be empty.
25134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3 && settings.is_ack()) {
2514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return builder.take();
2515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
25174ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
2518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    builder.WriteUInt32(values->size());
2519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != values->end();
25232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
25244ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (protocol_version() <= SPDY3) {
2525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      uint8 setting_flags = 0;
2526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (it->second.persist_value) {
2527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
2529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (it->second.persisted) {
2530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        setting_flags |= SETTINGS_FLAG_PERSISTED;
2531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
25324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      SettingsFlagsAndId flags_and_id(
25334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          setting_flags,
25344ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          SpdyConstants::SerializeSettingId(protocol_version(), it->first));
2535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      builder.WriteBytes(&id_and_flags_wire, 4);
2537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
2538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      builder.WriteUInt16(SpdyConstants::SerializeSettingId(protocol_version(),
2539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                            it->first));
25402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
25412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteUInt32(it->second.value);
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(size, builder.length());
25442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
25485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(GetPingSize(), protocol_version());
25494ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
255090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, PING, kNoFlags);
25515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    builder.WriteUInt32(static_cast<uint32>(ping.id()));
255290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
2553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint8 flags = 0;
2554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (ping.is_ack()) {
2555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      flags |= PING_FLAG_ACK;
2556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
25575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.BeginNewFrame(*this, PING, flags, 0);
25585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    builder.WriteUInt64(ping.id());
255990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
25602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetPingSize(), builder.length());
25612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
25622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
25632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeGoAway(
25652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyGoAwayIR& goaway) const {
25665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
25675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Compute the output buffer size, take opaque data into account.
25685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  uint16 expected_length = GetGoAwayMinimumSize();
25694ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3) {
25705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    expected_length += goaway.description().size();
25715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
25725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(expected_length, protocol_version());
25735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
25745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Serialize the GOAWAY frame.
25754ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
257690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
257790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
25785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.BeginNewFrame(*this, GOAWAY, 0, 0);
257990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
25805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
25815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // GOAWAY frames specify the last good stream id for all SPDY versions.
25822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(goaway.last_good_stream_id());
25835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
25845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // In SPDY3 and up, GOAWAY frames also specify the error status code.
25854ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() >= SPDY3) {
2586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // TODO(jgraettinger): Merge back to server-side.
2587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                             goaway.status()));
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // In SPDY4 and up, GOAWAY frames may also specify opaque data.
25924ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
25935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    builder.WriteBytes(goaway.description().data(),
25945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       goaway.description().size());
25955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(expected_length, builder.length());
25985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return builder.take();
25992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
26002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeHeaders(
26022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyHeadersIR& headers) {
26032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 flags = 0;
26042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (headers.fin()) {
26052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    flags |= CONTROL_FLAG_FIN;
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3) {
2608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // This will get overwritten if we overflow into a CONTINUATION frame.
2609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    flags |= HEADERS_FLAG_END_HEADERS;
2610a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (headers.has_priority()) {
2611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      flags |= HEADERS_FLAG_PRIORITY;
2612a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
2613a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The size of this frame, including variable-length name-value block.
261623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t size = GetHeadersMinimumSize();
2617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint32 priority = headers.priority();
2619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (headers.has_priority()) {
2620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (priority > GetLowestPriority()) {
2621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DLOG(DFATAL) << "Priority out-of-bounds.";
2622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      priority = GetLowestPriority();
2623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
2624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    size += 5;
2625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
26262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  string hpack_encoding;
26284ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3) {
26295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (enable_compression_) {
2630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetHpackEncoder()->EncodeHeaderSet(
26315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          headers.name_value_block(), &hpack_encoding);
26325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
2633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
26345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          headers.name_value_block(), &hpack_encoding);
26355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
263623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    size += hpack_encoding.size();
2637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (size > GetHeaderFragmentMaxSize()) {
26385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      size += GetNumberRequiredContinuationFrames(size) *
26395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              GetContinuationMinimumSize();
26405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      flags &= ~HEADERS_FLAG_END_HEADERS;
26415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
264223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
264323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    size += GetSerializedLength(headers.name_value_block());
264423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
264523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
26465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(size, protocol_version());
26474ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
264890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, HEADERS, flags);
264990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(headers.stream_id());
265090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
26515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.BeginNewFrame(*this,
26525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          HEADERS,
26535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          flags,
26545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          headers.stream_id());
265590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
26564ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY2) {
26572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    builder.WriteUInt16(0);  // Unused.
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
26602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() > SPDY3) {
2662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (headers.has_priority()) {
2663116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // TODO(jgraettinger): Plumb priorities and stream dependencies.
2664116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      builder.WriteUInt32(0);  // Non-exclusive bit and root stream ID.
2665116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      builder.WriteUInt8(MapPriorityToWeight(priority));
2666116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
26675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WritePayloadWithContinuation(&builder,
26685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 hpack_encoding,
26695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 headers.stream_id(),
26705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 HEADERS);
267123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
267223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    SerializeNameValueBlock(&builder, headers);
267323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
26742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (debug_visitor_) {
2676116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // SPDY4 uses HPACK for header compression. However, continue to
2677116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // use GetSerializedLength() for an apples-to-apples comparision of
2678116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // compression performance between HPACK and SPDY w/ deflate.
2679116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const size_t payload_len =
268023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        GetSerializedLength(protocol_version(),
268123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                            &(headers.name_value_block()));
26827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
26837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          HEADERS,
26847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          payload_len,
26857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          builder.length());
26867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
26877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
26882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
26922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpdyWindowUpdateIR& window_update) const {
26935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
26944ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY3) {
269590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
269690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    builder.WriteUInt32(window_update.stream_id());
269790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
26985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder.BeginNewFrame(*this,
26995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          WINDOW_UPDATE,
27005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          kNoFlags,
27015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          window_update.stream_id());
270290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
27032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder.WriteUInt32(window_update.delta());
27042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(GetWindowUpdateSize(), builder.length());
27052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return builder.take();
27062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
27072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
27095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_LT(SPDY3, protocol_version());
27105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
27115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
27125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return builder.take();
27135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
27145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
27157dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSpdyFrame* SpdyFramer::SerializePushPromise(
27167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const SpdyPushPromiseIR& push_promise) {
27174ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  DCHECK_LT(SPDY3, protocol_version());
2718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint8 flags = 0;
2719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // This will get overwritten if we overflow into a CONTINUATION frame.
2720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
27217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The size of this frame, including variable-length name-value block.
272223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t size = GetPushPromiseMinimumSize();
272323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
272423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  string hpack_encoding;
2725116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (enable_compression_) {
2726116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetHpackEncoder()->EncodeHeaderSet(
2727116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        push_promise.name_value_block(), &hpack_encoding);
272823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
2729116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2730116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        push_promise.name_value_block(), &hpack_encoding);
2731116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2732116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size += hpack_encoding.size();
2733116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (size > GetHeaderFragmentMaxSize()) {
2734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    size += GetNumberRequiredContinuationFrames(size) *
2735116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            GetContinuationMinimumSize();
2736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
273723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
27387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
27395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(size, protocol_version());
27405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  builder.BeginNewFrame(*this,
27415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        PUSH_PROMISE,
27425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        flags,
27435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        push_promise.stream_id());
27447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  builder.WriteUInt32(push_promise.promised_stream_id());
27457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
27467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2747116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  WritePayloadWithContinuation(&builder,
2748116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               hpack_encoding,
2749116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               push_promise.stream_id(),
2750116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               PUSH_PROMISE);
27517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
27527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (debug_visitor_) {
2753116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // SPDY4 uses HPACK for header compression. However, continue to
2754116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // use GetSerializedLength() for an apples-to-apples comparision of
2755116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // compression performance between HPACK and SPDY w/ deflate.
2756116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const size_t payload_len =
275723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        GetSerializedLength(protocol_version(),
275823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                            &(push_promise.name_value_block()));
27597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2760116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          PUSH_PROMISE,
2761116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          payload_len,
2762116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          builder.length());
27637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
27647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
27657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return builder.take();
27667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
27677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
276823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// TODO(jgraettinger): This implementation is incorrect. The continuation
276923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// frame continues a previously-begun HPACK encoding; it doesn't begin a
277023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// new one. Figure out whether it makes sense to keep SerializeContinuation().
2771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SpdyFrame* SpdyFramer::SerializeContinuation(
2772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const SpdyContinuationIR& continuation) {
27734ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  CHECK_LT(SPDY3, protocol_version());
2774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint8 flags = 0;
2775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (continuation.end_headers()) {
2776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    flags |= HEADERS_FLAG_END_HEADERS;
2777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2778a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The size of this frame, including variable-length name-value block.
278023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t size = GetContinuationMinimumSize();
278123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  string hpack_encoding;
27825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (enable_compression_) {
2783cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GetHpackEncoder()->EncodeHeaderSet(
27845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        continuation.name_value_block(), &hpack_encoding);
27855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
2786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
27875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        continuation.name_value_block(), &hpack_encoding);
27885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
278923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size += hpack_encoding.size();
2790a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
27915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder builder(size, protocol_version());
27925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  builder.BeginNewFrame(*this, CONTINUATION, flags,
2793a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      continuation.stream_id());
2794a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2795a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
279623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2797a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return builder.take();
2798a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
2799a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2800cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) {
2801cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LT(SPDY3, protocol_version());
2802cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t size = GetAltSvcMinimumSize();
2803cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size += altsvc.protocol_id().length();
2804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size += altsvc.host().length();
2805cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size += altsvc.origin().length();
2806cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdyFrameBuilder builder(size, protocol_version());
2808cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
2809cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2810cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteUInt32(altsvc.max_age());
2811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteUInt16(altsvc.port());
2812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteUInt8(0);  // Reserved.
2813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteUInt8(altsvc.protocol_id().length());
2814cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteBytes(altsvc.protocol_id().data(),
2815cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     altsvc.protocol_id().length());
2816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteUInt8(altsvc.host().length());
2817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteBytes(altsvc.host().data(), altsvc.host().length());
2818cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
2819cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2820cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return builder.take();
2821cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
2822cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2823116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) {
2824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_LT(SPDY3, protocol_version());
2825116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t size = GetPrioritySize();
2826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2827116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SpdyFrameBuilder builder(size, protocol_version());
2828116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
2829116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2830116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Make sure the highest-order bit in the parent stream id is zeroed out.
2831116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 parent_stream_id = priority.parent_stream_id() & 0x7fffffff;
2832116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 exclusive = priority.exclusive() ? 0x80000000 : 0;
2833116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Set the one-bit exclusivity flag.
2834116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint32 flag_and_parent_id = parent_stream_id | exclusive;
2835116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.WriteUInt32(flag_and_parent_id);
2836116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  builder.WriteUInt8(priority.weight());
2837116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(GetPrioritySize(), builder.length());
2838116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return builder.take();
2839116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
2840116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
2842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass FrameSerializationVisitor : public SpdyFrameVisitor {
2844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
2845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual ~FrameSerializationVisitor() {}
2847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    frame_.reset(framer_->SerializeData(data));
2852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
2853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeSynStream(syn_stream));
2855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeSynReply(syn_reply));
2858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeRstStream(rst_stream));
2861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeSettings(settings));
2864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializePing(ping));
2867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeGoAway(goaway));
2870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeHeaders(headers));
2873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitWindowUpdate(
2875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const SpdyWindowUpdateIR& window_update) OVERRIDE {
2876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeWindowUpdate(window_update));
2877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    frame_.reset(framer_->SerializeBlocked(blocked));
2880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
28817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void VisitPushPromise(
28827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const SpdyPushPromiseIR& push_promise) OVERRIDE {
28837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    frame_.reset(framer_->SerializePushPromise(push_promise));
28847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2885a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void VisitContinuation(
2886a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const SpdyContinuationIR& continuation) OVERRIDE {
2887a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    frame_.reset(framer_->SerializeContinuation(continuation));
2888a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2889cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) OVERRIDE {
2890cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    frame_.reset(framer_->SerializeAltSvc(altsvc));
2891cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2892116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void VisitPriority(const SpdyPriorityIR& priority) OVERRIDE {
2893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    frame_.reset(framer_->SerializePriority(priority));
2894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
2897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyFramer* framer_;
2898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdySerializedFrame> frame_;
2899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
2900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
2902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FrameSerializationVisitor visitor(this);
2905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  frame.Visit(&visitor);
2906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return visitor.ReleaseSerializedFrame();
2907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
290923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
29104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  CHECK_GE(SPDY3, protocol_version());
29112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t uncompressed_length =
291223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    GetSerializedLength(protocol_version(), &headers);
29132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!enable_compression_) {
29142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return uncompressed_length;
29152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
29162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  z_stream* compressor = GetHeaderCompressor();
29172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since we'll be performing lots of flushes when compressing the data,
29182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // zlib's lower bounds may be insufficient.
29192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 2 * deflateBound(compressor, uncompressed_length);
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2923116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize();
29245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_GT(protocol_version(), SPDY3);
29255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_GT(size, kMaxControlFrameSize);
29265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  size_t overflow = size - kMaxControlFrameSize;
29275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1;
29285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
29295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
29305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
29315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                              const string& hpack_encoding,
29325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                              SpdyStreamId stream_id,
29335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                              SpdyFrameType type) {
2934116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize();
29355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
29365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // In addition to the prefix, fixed_field_size includes the size of
29375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // any fields that come before the variable-length name/value block.
29385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    size_t fixed_field_size = 0;
29395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    uint8 end_flag = 0;
29405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    uint8 flags = 0;
29415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (type == HEADERS) {
29425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      fixed_field_size = GetHeadersMinimumSize();
29435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      end_flag = HEADERS_FLAG_END_HEADERS;
29445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (type == PUSH_PROMISE) {
29455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      fixed_field_size = GetPushPromiseMinimumSize();
29465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
29475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
29485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
29495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                  << FrameTypeToString(type);
29505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
29515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
29525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Write as much of the payload as possible into the initial frame.
29535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    size_t bytes_remaining = hpack_encoding.size() -
29545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        std::min(hpack_encoding.size(),
29555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 kMaxControlFrameSize - fixed_field_size);
29565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    builder->WriteBytes(&hpack_encoding[0],
29575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        hpack_encoding.size() - bytes_remaining);
29585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
29595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (bytes_remaining > 0) {
29605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      builder->OverwriteLength(*this,
29615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          kMaxControlFrameSize - GetControlFrameHeaderSize());
29625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
29635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
29645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Tack on CONTINUATION frames for the overflow.
29655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    while (bytes_remaining > 0) {
29665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      size_t bytes_to_write = std::min(bytes_remaining,
29675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       kMaxControlFrameSize -
29685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       GetContinuationMinimumSize());
29695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Write CONTINUATION frame prefix.
29705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (bytes_remaining == bytes_to_write) {
29715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        flags |= end_flag;
29725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
29735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      builder->BeginNewFrame(*this,
29745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                             CONTINUATION,
29755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                             flags,
29765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                             stream_id);
29775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Write payload fragment.
29785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      builder->WriteBytes(&hpack_encoding[hpack_encoding.size() -
29795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          bytes_remaining],
29805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          bytes_to_write);
29815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bytes_remaining -= bytes_to_write;
29825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
29835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
29845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following compression setting are based on Brian Olson's analysis. See
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for more details.
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_SYSTEM_ZLIB)
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// System zlib is not expected to have workaround for http://crbug.com/139744,
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so disable compression in that case.
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Remove the special case when it's no longer necessary.
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 0;
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // !defined(USE_SYSTEM_ZLIB)
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 9;
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(USE_SYSTEM_ZLIB)
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorWindowSizeInBits = 11;
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorMemLevel = 1;
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderCompressor() {
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_compressor_.get())
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return header_compressor_.get();  // Already initialized.
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_compressor_.reset(new z_stream);
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(header_compressor_.get(), 0, sizeof(z_stream));
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = deflateInit2(header_compressor_.get(),
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kCompressorLevel,
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             Z_DEFLATED,
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kCompressorWindowSizeInBits,
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kCompressorMemLevel,
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             Z_DEFAULT_STRATEGY);
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success == Z_OK) {
30134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    const char* dictionary = (protocol_version() <= SPDY2) ?
30144ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        kV2Dictionary : kV3Dictionary;
30154ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    const int dictionary_size = (protocol_version() <= SPDY2) ?
30164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        kV2DictionarySize : kV3DictionarySize;
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success = deflateSetDictionary(header_compressor_.get(),
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   reinterpret_cast<const Bytef*>(dictionary),
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   dictionary_size);
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success != Z_OK) {
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "deflateSetDictionary failure: " << success;
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header_compressor_.reset(NULL);
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return header_compressor_.get();
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderDecompressor() {
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_decompressor_.get())
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return header_decompressor_.get();  // Already initialized.
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header_decompressor_.reset(new z_stream);
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(header_decompressor_.get(), 0, sizeof(z_stream));
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int success = inflateInit(header_decompressor_.get());
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success != Z_OK) {
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "inflateInit failure: " << success;
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header_decompressor_.reset(NULL);
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return header_decompressor_.get();
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)HpackEncoder* SpdyFramer::GetHpackEncoder() {
3046cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LT(SPDY3, spdy_version_);
3047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (hpack_encoder_.get() == NULL) {
3048cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3049cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
3050cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return hpack_encoder_.get();
3051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
3052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)HpackDecoder* SpdyFramer::GetHpackDecoder() {
3054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LT(SPDY3, spdy_version_);
3055cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (hpack_decoder_.get() == NULL) {
3056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
3058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return hpack_decoder_.get();
3059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
3060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const float kSteps = 255.9f / 7.f;
3063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<uint8>(kSteps * (7.f - priority));
3064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
3065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const float kSteps = 255.9f / 7.f;
3068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<SpdyPriority>(7.f - weight / kSteps);
3069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
3070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Incrementally decompress the control frame's header block, feeding the
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// result to the visitor in chunks. Continue this until the visitor
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// indicates that it cannot process any more data, or (more commonly) we
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run out of data to deliver.
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
30762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyStreamId stream_id,
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* data,
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t len) {
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get a decompressor or set error.
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z_stream* decomp = GetHeaderDecompressor();
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (decomp == NULL) {
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_error(SPDY_DECOMPRESS_FAILURE);
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool processed_successfully = true;
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer[kHeaderDataChunkMaxSize];
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomp->avail_in = len;
3092ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3093ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // signal an error back in ProcessControlFrameBeforeHeaderBlock.  So if we've
3094ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // reached this method successfully, stream_id should be nonzero.
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(0u, stream_id);
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (decomp->avail_in > 0 && processed_successfully) {
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decomp->next_out = reinterpret_cast<Bytef*>(buffer);
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decomp->avail_out = arraysize(buffer);
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = inflate(decomp, Z_SYNC_FLUSH);
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == Z_NEED_DICT) {
31024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
31034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                                             : kV3Dictionary;
31044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      const int dictionary_size = (protocol_version() <= SPDY2) ?
31054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          kV2DictionarySize : kV3DictionarySize;
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const DictionaryIds& ids = g_dictionary_ids.Get();
31074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      const uLong dictionary_id = (protocol_version() <= SPDY2) ?
31084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          ids.v2_dictionary_id : ids.v3_dictionary_id;
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Need to try again with the right dictionary.
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (decomp->adler == dictionary_id) {
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = inflateSetDictionary(decomp,
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  reinterpret_cast<const Bytef*>(dictionary),
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  dictionary_size);
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv == Z_OK)
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = inflate(decomp, Z_SYNC_FLUSH);
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Inflate will generate a Z_BUF_ERROR if it runs out of input
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // without producing any output.  The input is consumed and
31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffered internally by zlib so we can detect this condition by
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // checking if avail_in is 0 after the call to inflate.
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((rv == Z_OK) || input_exhausted) {
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (decompressed_len > 0) {
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        processed_successfully = visitor_->OnControlFrameHeaderData(
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            stream_id, buffer, decompressed_len);
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!processed_successfully) {
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Assume that the problem was the header block was too large for the
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // visitor.
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DLOG(WARNING) << "inflate failure: " << rv << " " << len;
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_DECOMPRESS_FAILURE);
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processed_successfully = false;
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return processed_successfully;
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
31452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyStreamId stream_id, const char* data, size_t len) {
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool read_successfully = true;
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (read_successfully && len > 0) {
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           bytes_to_deliver);
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data += bytes_to_deliver;
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= bytes_to_deliver;
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!read_successfully) {
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Assume that the problem was the header block was too large for the
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // visitor.
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return read_successfully;
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlockWithoutCompression(
31632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyFrameBuilder* builder,
316423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyNameValueBlock& name_value_block) const {
31652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Serialize number of headers.
31664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (protocol_version() <= SPDY2) {
316723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    builder->WriteUInt16(name_value_block.size());
316823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
316923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    builder->WriteUInt32(name_value_block.size());
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Serialize each header.
3173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
3174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       it != name_value_block.end();
31752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
31764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (protocol_version() <= SPDY2) {
31772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteString(it->first);
31782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteString(it->second);
31792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
31802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteStringPiece32(it->first);
31812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->WriteStringPiece32(it->second);
31822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
31832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlock(
31872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyFrameBuilder* builder,
318823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyFrameWithNameValueBlockIR& frame) {
31894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  CHECK_GE(SPDY3, protocol_version());
31902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!enable_compression_) {
3191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return SerializeNameValueBlockWithoutCompression(builder,
319223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                     frame.name_value_block());
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // First build an uncompressed version to be fed into the compressor.
31962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t uncompressed_len = GetSerializedLength(
319723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      protocol_version(), &(frame.name_value_block()));
31985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
320023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                            frame.name_value_block());
32012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
32022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  z_stream* compressor = GetHeaderCompressor();
32042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!compressor) {
32052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(DFATAL) << "Could not obtain compressor.";
32062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StatsCounter compressed_frames("spdy.CompressedFrames");
32102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
32112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
32122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create an output frame.
32142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since we'll be performing lots of flushes when compressing the data,
32152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // zlib's lower bounds may be insufficient.
32162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
32172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(akalin): Avoid the duplicate calculation with
32182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSerializedLength(const SpdyHeaderBlock&).
32192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int compressed_max_size =
32202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      2 * deflateBound(compressor, uncompressed_len);
32212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(phajdan.jr): Clean up after we no longer need
32232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to workaround http://crbug.com/139744.
32242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB)
32252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
32262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->avail_in = uncompressed_len;
32272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_SYSTEM_ZLIB)
32282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->next_out = reinterpret_cast<Bytef*>(
32292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      builder->GetWritableBuffer(compressed_max_size));
32302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressor->avail_out = compressed_max_size;
32312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(phajdan.jr): Clean up after we no longer need
32332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to workaround http://crbug.com/139744.
32342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB)
32352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv = deflate(compressor, Z_SYNC_FLUSH);
32362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != Z_OK) {  // How can we know that it compressed everything?
32372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This shouldn't happen, right?
32382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "deflate failure: " << rv;
32392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(akalin): Upstream this return.
32402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
32412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
32422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
32432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
32442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(USE_SYSTEM_ZLIB)
32452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int compressed_size = compressed_max_size - compressor->avail_out;
32472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder->Seek(compressed_size);
32482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  builder->RewriteLength(*this);
32492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pre_compress_bytes.Add(uncompressed_len);
32512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  post_compress_bytes.Add(compressed_size);
32522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  compressed_frames.Increment();
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
3257