spdy_framer.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(rtenhove) clean up frame buffer size calculations so that we aren't
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constantly adding and subtracting header sizes; this is ugly and error-
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prone.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_framer.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/valgrind/memcheck.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/spdy/spdy_frame_builder.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_reader.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_bitmasks.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/zlib.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Compute the id of our dictionary so that we know we're using the
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// right one when asked for it.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uLong CalculateDictionaryId(const char* dictionary,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const size_t dictionary_size) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uLong initial_value = adler32(0L, Z_NULL, 0);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return adler32(initial_value,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 reinterpret_cast<const Bytef*>(dictionary),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 dictionary_size);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DictionaryIds {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryIds()
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uLong v2_dictionary_id;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uLong v3_dictionary_id;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adler ID for the SPDY header compressor dictionaries. Note that they are
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// initialized lazily to avoid static initializers.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to indicate no flags in a SPDY flags field.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 kNoFlags = 0;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int SpdyFramer::kMinSpdyVersion = kSpdyVersion2;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int SpdyFramer::kMaxSpdyVersion = kSpdyVersion4;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SpdyStreamId SpdyFramer::kInvalidStream = -1;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The size of the control frame buffer. Must be >= the minimum size of the
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calculation details.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kControlFrameBufferSize = 18;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_SPDY_STATE_CHANGES
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate)                                  \
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {                                                          \
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << "Changing state from: "                        \
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << StateToString(state_)                          \
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << " to " << StateToString(newstate) << "\n";     \
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ != SPDY_ERROR);                               \
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(previous_state_, state_);                         \
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;                                   \
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = newstate;                                          \
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CHANGE_STATE(newstate)                                  \
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {                                                          \
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(state_ != SPDY_ERROR);                               \
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(previous_state_, state_);                         \
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_state_ = state_;                                   \
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = newstate;                                          \
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      uint32 wire) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version < 3) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertFlagsAndIdForSpdy2(&wire);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : flags_(flags), id_(id & 0x00ffffff) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(1u << 24, id) << "SPDY setting ID too large.";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 SettingsFlagsAndId::GetWireFormat(int version) const {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version < 3) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConvertFlagsAndIdForSpdy2(&wire);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return wire;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is used to preserve buggy behavior and works on both
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// little-endian and big-endian hosts.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as vice versa).
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8* wire_array = reinterpret_cast<uint8*>(val);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(wire_array[0], wire_array[3]);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::swap(wire_array[1], wire_array[2]);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::SpdyCredential() : slot(0) {}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::~SpdyCredential() {}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::SpdyFramer(int version)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : current_frame_buffer_(new char[kControlFrameBufferSize]),
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enable_compression_(true),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_(NULL),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      debug_visitor_(NULL),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_protocol_("SPDY"),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spdy_version_(version),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syn_frame_processed_(false),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      probable_http_response_(false) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(kMaxSpdyVersion, version);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(kMinSpdyVersion, version);
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Reset();
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::~SpdyFramer() {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_compressor_.get()) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deflateEnd(header_compressor_.get());
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_decompressor_.get()) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inflateEnd(header_decompressor_.get());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::Reset() {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = SPDY_RESET;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  previous_state_ = SPDY_RESET;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_code_ = SPDY_NO_ERROR;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remaining_data_length_ = 0;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remaining_control_header_ = 0;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_frame_buffer_length_ = 0;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_frame_type_ = DATA;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_frame_flags_ = 0;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_frame_length_ = 0;
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  current_frame_stream_id_ = kInvalidStream;
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  settings_scratch_.Reset();
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::GetDataFrameMinimumSize() const {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Size, in bytes, of the data frame header. Future versions of SPDY
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will likely vary this, so we allow for the flexibility of a function call
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for this value as opposed to a constant.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 8;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size, in bytes, of the control frame header.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::GetControlFrameHeaderSize() const {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (protocol_version()) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 3:
168      return 8;
169    case 4:
170      return 4;
171  }
172  LOG(DFATAL) << "Unhandled SPDY version.";
173  return 0;
174}
175
176size_t SpdyFramer::GetSynStreamMinimumSize() const {
177  // Size, in bytes, of a SYN_STREAM frame not including the variable-length
178  // name-value block. Calculated as:
179  // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot)
180  return GetControlFrameHeaderSize() + 10;
181}
182
183size_t SpdyFramer::GetSynReplyMinimumSize() const {
184  // Size, in bytes, of a SYN_REPLY frame not including the variable-length
185  // name-value block. Calculated as:
186  // control frame header + 4 (stream ID)
187  size_t size = GetControlFrameHeaderSize() + 4;
188
189  // In SPDY 2, there were 2 unused bytes before payload.
190  if (protocol_version() < 3) {
191    size += 2;
192  }
193
194  return size;
195}
196
197size_t SpdyFramer::GetRstStreamSize() const {
198  // Size, in bytes, of a RST_STREAM frame. Calculated as:
199  // control frame header + 4 (stream id) + 4 (status code)
200  return GetControlFrameHeaderSize() + 8;
201}
202
203size_t SpdyFramer::GetSettingsMinimumSize() const {
204  // Size, in bytes, of a SETTINGS frame not including the IDs and values
205  // from the variable-length value block. Calculated as:
206  // control frame header + 4 (number of ID/value pairs)
207  return GetControlFrameHeaderSize() + 4;
208}
209
210size_t SpdyFramer::GetPingSize() const {
211  // Size, in bytes, of this PING frame. Calculated as:
212  // control frame header + 4 (id)
213  return GetControlFrameHeaderSize() + 4;
214}
215
216size_t SpdyFramer::GetGoAwaySize() const {
217  // Size, in bytes, of this GOAWAY frame. Calculated as:
218  // control frame header + 4 (last good stream id)
219  size_t size = GetControlFrameHeaderSize() + 4;
220
221  // SPDY 3+ GOAWAY frames also contain a status.
222  if (protocol_version() >= 3) {
223    size += 4;
224  }
225
226  return size;
227}
228
229size_t SpdyFramer::GetHeadersMinimumSize() const  {
230  // Size, in bytes, of a HEADERS frame not including the variable-length
231  // name-value block. Calculated as:
232  // control frame header + 4 (stream ID)
233  size_t size = GetControlFrameHeaderSize() + 4;
234
235  // In SPDY 2, there were 2 unused bytes before payload.
236  if (protocol_version() < 3) {
237    size += 2;
238  }
239
240  return size;
241}
242
243size_t SpdyFramer::GetWindowUpdateSize() const {
244  // Size, in bytes, of this WINDOW_UPDATE frame. Calculated as:
245  // control frame header + 4 (stream id) + 4 (delta)
246  return GetControlFrameHeaderSize() + 8;
247}
248
249size_t SpdyFramer::GetCredentialMinimumSize() const {
250  // Size, in bytes, of a CREDENTIAL frame sans variable-length certificate list
251  // and proof. Calculated as:
252  // control frame header + 2 (slot)
253  return GetControlFrameHeaderSize() + 2;
254}
255
256size_t SpdyFramer::GetFrameMinimumSize() const {
257  return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
258}
259
260size_t SpdyFramer::GetFrameMaximumSize() const {
261  return (protocol_version() < 4) ? 0xffffff : 0xffff;
262}
263
264size_t SpdyFramer::GetDataFrameMaximumPayload() const {
265  return GetFrameMaximumSize() - GetDataFrameMinimumSize();
266}
267
268const char* SpdyFramer::StateToString(int state) {
269  switch (state) {
270    case SPDY_ERROR:
271      return "ERROR";
272    case SPDY_AUTO_RESET:
273      return "AUTO_RESET";
274    case SPDY_RESET:
275      return "RESET";
276    case SPDY_READING_COMMON_HEADER:
277      return "READING_COMMON_HEADER";
278    case SPDY_CONTROL_FRAME_PAYLOAD:
279      return "CONTROL_FRAME_PAYLOAD";
280    case SPDY_IGNORE_REMAINING_PAYLOAD:
281      return "IGNORE_REMAINING_PAYLOAD";
282    case SPDY_FORWARD_STREAM_FRAME:
283      return "FORWARD_STREAM_FRAME";
284    case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
285      return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
286    case SPDY_CONTROL_FRAME_HEADER_BLOCK:
287      return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
288    case SPDY_CREDENTIAL_FRAME_PAYLOAD:
289      return "SPDY_CREDENTIAL_FRAME_PAYLOAD";
290    case SPDY_SETTINGS_FRAME_PAYLOAD:
291      return "SPDY_SETTINGS_FRAME_PAYLOAD";
292  }
293  return "UNKNOWN_STATE";
294}
295
296void SpdyFramer::set_error(SpdyError error) {
297  DCHECK(visitor_);
298  error_code_ = error;
299  CHANGE_STATE(SPDY_ERROR);
300  visitor_->OnError(this);
301}
302
303const char* SpdyFramer::ErrorCodeToString(int error_code) {
304  switch (error_code) {
305    case SPDY_NO_ERROR:
306      return "NO_ERROR";
307    case SPDY_INVALID_CONTROL_FRAME:
308      return "INVALID_CONTROL_FRAME";
309    case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
310      return "CONTROL_PAYLOAD_TOO_LARGE";
311    case SPDY_ZLIB_INIT_FAILURE:
312      return "ZLIB_INIT_FAILURE";
313    case SPDY_UNSUPPORTED_VERSION:
314      return "UNSUPPORTED_VERSION";
315    case SPDY_DECOMPRESS_FAILURE:
316      return "DECOMPRESS_FAILURE";
317    case SPDY_COMPRESS_FAILURE:
318      return "COMPRESS_FAILURE";
319    case SPDY_INVALID_DATA_FRAME_FLAGS:
320      return "SPDY_INVALID_DATA_FRAME_FLAGS";
321    case SPDY_INVALID_CONTROL_FRAME_FLAGS:
322      return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
323  }
324  return "UNKNOWN_ERROR";
325}
326
327const char* SpdyFramer::StatusCodeToString(int status_code) {
328  switch (status_code) {
329    case RST_STREAM_INVALID:
330      return "INVALID";
331    case RST_STREAM_PROTOCOL_ERROR:
332      return "PROTOCOL_ERROR";
333    case RST_STREAM_INVALID_STREAM:
334      return "INVALID_STREAM";
335    case RST_STREAM_REFUSED_STREAM:
336      return "REFUSED_STREAM";
337    case RST_STREAM_UNSUPPORTED_VERSION:
338      return "UNSUPPORTED_VERSION";
339    case RST_STREAM_CANCEL:
340      return "CANCEL";
341    case RST_STREAM_INTERNAL_ERROR:
342      return "INTERNAL_ERROR";
343    case RST_STREAM_FLOW_CONTROL_ERROR:
344      return "FLOW_CONTROL_ERROR";
345    case RST_STREAM_STREAM_IN_USE:
346      return "STREAM_IN_USE";
347    case RST_STREAM_STREAM_ALREADY_CLOSED:
348      return "STREAM_ALREADY_CLOSED";
349    case RST_STREAM_INVALID_CREDENTIALS:
350      return "INVALID_CREDENTIALS";
351    case RST_STREAM_FRAME_TOO_LARGE:
352      return "FRAME_TOO_LARGE";
353  }
354  return "UNKNOWN_STATUS";
355}
356
357const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
358  switch (type) {
359    case DATA:
360      return "DATA";
361    case SYN_STREAM:
362      return "SYN_STREAM";
363    case SYN_REPLY:
364      return "SYN_REPLY";
365    case RST_STREAM:
366      return "RST_STREAM";
367    case SETTINGS:
368      return "SETTINGS";
369    case NOOP:
370      return "NOOP";
371    case PING:
372      return "PING";
373    case GOAWAY:
374      return "GOAWAY";
375    case HEADERS:
376      return "HEADERS";
377    case WINDOW_UPDATE:
378      return "WINDOW_UPDATE";
379    case CREDENTIAL:
380      return "CREDENTIAL";
381  }
382  return "UNKNOWN_CONTROL_TYPE";
383}
384
385size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
386  DCHECK(visitor_);
387  DCHECK(data);
388
389  size_t original_len = len;
390  do {
391    previous_state_ = state_;
392    switch (state_) {
393      case SPDY_ERROR:
394        goto bottom;
395
396      case SPDY_AUTO_RESET:
397      case SPDY_RESET:
398        Reset();
399        if (len > 0) {
400          CHANGE_STATE(SPDY_READING_COMMON_HEADER);
401        }
402        break;
403
404      case SPDY_READING_COMMON_HEADER: {
405        size_t bytes_read = ProcessCommonHeader(data, len);
406        len -= bytes_read;
407        data += bytes_read;
408        break;
409      }
410
411      case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
412        // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY,
413        // HEADERS) take a different path through the state machine - they
414        // will go:
415        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
416        //   2. SPDY_CONTROL_FRAME_HEADER_BLOCK
417        //
418        // SETTINGS frames take a slightly modified route:
419        //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
420        //   2. SPDY_SETTINGS_FRAME_PAYLOAD
421        //
422        //  All other control frames will use the alternate route directly to
423        //  SPDY_CONTROL_FRAME_PAYLOAD
424        int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
425        len -= bytes_read;
426        data += bytes_read;
427        break;
428      }
429
430      case SPDY_SETTINGS_FRAME_PAYLOAD: {
431        int bytes_read = ProcessSettingsFramePayload(data, len);
432        len -= bytes_read;
433        data += bytes_read;
434        break;
435      }
436
437      case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
438        int bytes_read = ProcessControlFrameHeaderBlock(data, len);
439        len -= bytes_read;
440        data += bytes_read;
441        break;
442      }
443
444      case SPDY_CREDENTIAL_FRAME_PAYLOAD: {
445        size_t bytes_read = ProcessCredentialFramePayload(data, len);
446        len -= bytes_read;
447        data += bytes_read;
448        break;
449      }
450
451      case SPDY_CONTROL_FRAME_PAYLOAD: {
452        size_t bytes_read = ProcessControlFramePayload(data, len);
453        len -= bytes_read;
454        data += bytes_read;
455        break;
456      }
457
458      case SPDY_IGNORE_REMAINING_PAYLOAD:
459        // control frame has too-large payload
460        // intentional fallthrough
461      case SPDY_FORWARD_STREAM_FRAME: {
462        size_t bytes_read = ProcessDataFramePayload(data, len);
463        len -= bytes_read;
464        data += bytes_read;
465        break;
466      }
467      default:
468        LOG(DFATAL) << "Invalid value for " << display_protocol_
469                    << " framer state: " << state_;
470        // This ensures that we don't infinite-loop if state_ gets an
471        // invalid value somehow, such as due to a SpdyFramer getting deleted
472        // from a callback it calls.
473        goto bottom;
474    }
475  } while (state_ != previous_state_);
476 bottom:
477  DCHECK(len == 0 || state_ == SPDY_ERROR);
478  if (current_frame_buffer_length_ == 0 &&
479      remaining_data_length_ == 0 &&
480      remaining_control_header_ == 0) {
481    DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
482        << "State: " << StateToString(state_);
483  }
484
485  return original_len - len;
486}
487
488size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
489  // This should only be called when we're in the SPDY_READING_COMMON_HEADER
490  // state.
491  DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
492
493  size_t original_len = len;
494
495  // Update current frame buffer as needed.
496  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
497    size_t bytes_desired =
498        GetControlFrameHeaderSize() - current_frame_buffer_length_;
499    UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
500  }
501
502  if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
503    // Not enough information to do anything meaningful.
504    return original_len - len;
505  }
506
507  // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
508  // when processing DATA frames below.
509  scoped_ptr<SpdyFrameReader> reader(
510      new SpdyFrameReader(current_frame_buffer_.get(),
511                          current_frame_buffer_length_));
512
513  uint16 version = 0;
514  bool is_control_frame = false;
515
516  uint16 control_frame_type_field = DATA;
517  // ProcessControlFrameHeader() will set current_frame_type_ to the
518  // correct value if this is a valid control frame.
519  current_frame_type_ = DATA;
520  if (protocol_version() < 4) {
521    bool successful_read = reader->ReadUInt16(&version);
522    DCHECK(successful_read);
523    is_control_frame = (version & kControlFlagMask) != 0;
524    version &= ~kControlFlagMask;  // Only valid for control frames.
525
526    if (is_control_frame) {
527      // We check control_frame_type_field's validity in
528      // ProcessControlFrameHeader().
529      successful_read = reader->ReadUInt16(&control_frame_type_field);
530    } else {
531      reader->Rewind();
532      successful_read = reader->ReadUInt31(&current_frame_stream_id_);
533    }
534    DCHECK(successful_read);
535
536    successful_read = reader->ReadUInt8(&current_frame_flags_);
537    DCHECK(successful_read);
538
539    uint32 length_field = 0;
540    successful_read = reader->ReadUInt24(&length_field);
541    DCHECK(successful_read);
542    remaining_data_length_ = length_field;
543    current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
544  } else {
545    // TODO(hkhalil): Avoid re-reading fields as possible for DATA frames?
546    version = protocol_version();
547    uint16 length_field = 0;
548    bool successful_read = reader->ReadUInt16(&length_field);
549    DCHECK(successful_read);
550    current_frame_length_ = length_field;
551
552    uint8 control_frame_type_field_uint8 = DATA;
553    successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
554    DCHECK(successful_read);
555    // We check control_frame_type_field's validity in
556    // ProcessControlFrameHeader().
557    control_frame_type_field = control_frame_type_field_uint8;
558    is_control_frame = (control_frame_type_field != DATA);
559
560    successful_read = reader->ReadUInt8(&current_frame_flags_);
561    DCHECK(successful_read);
562
563    if (!is_control_frame) {
564      // We may not have the entirety of the DATA frame header.
565      if (current_frame_buffer_length_ < GetDataFrameMinimumSize()) {
566        size_t bytes_desired =
567            GetDataFrameMinimumSize() - current_frame_buffer_length_;
568        UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
569        if (current_frame_buffer_length_ < GetDataFrameMinimumSize()) {
570          return original_len - len;
571        }
572      }
573      // Construct a new SpdyFrameReader aware of the new frame length.
574      reader.reset(new SpdyFrameReader(current_frame_buffer_.get(),
575                                       current_frame_buffer_length_));
576      reader->Seek(GetControlFrameHeaderSize());
577      successful_read = reader->ReadUInt31(&current_frame_stream_id_);
578      DCHECK(successful_read);
579    }
580    remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
581  }
582  DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
583                             : GetDataFrameMinimumSize(),
584            reader->GetBytesConsumed());
585  DCHECK_EQ(current_frame_length_,
586            remaining_data_length_ + reader->GetBytesConsumed());
587
588  // This is just a sanity check for help debugging early frame errors.
589  if (remaining_data_length_ > 1000000u) {
590    // The strncmp for 5 is safe because we only hit this point if we
591    // have kMinCommonHeader (8) bytes
592    if (!syn_frame_processed_ &&
593        strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
594      LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
595                   << " request";
596      probable_http_response_ = true;
597    } else {
598      LOG(WARNING) << "Unexpectedly large frame.  " << display_protocol_
599                   << " session is likely corrupt.";
600    }
601  }
602
603  // if we're here, then we have the common header all received.
604  if (!is_control_frame) {
605    if (current_frame_flags_ & ~DATA_FLAG_FIN) {
606      set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
607    } else {
608      visitor_->OnDataFrameHeader(current_frame_stream_id_,
609                                  remaining_data_length_,
610                                  current_frame_flags_ & DATA_FLAG_FIN);
611      if (remaining_data_length_ > 0) {
612        CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
613      } else {
614        // Empty data frame.
615        if (current_frame_flags_ & DATA_FLAG_FIN) {
616          visitor_->OnStreamFrameData(
617              current_frame_stream_id_, NULL, 0, true);
618        }
619        CHANGE_STATE(SPDY_AUTO_RESET);
620      }
621    }
622  } else if (version != spdy_version_) {
623    // We check version before we check validity: version can never be
624    // 'invalid', it can only be unsupported.
625    DLOG(INFO) << "Unsupported SPDY version " << version
626               << " (expected " << spdy_version_ << ")";
627    set_error(SPDY_UNSUPPORTED_VERSION);
628  } else {
629    ProcessControlFrameHeader(control_frame_type_field);
630  }
631
632  return original_len - len;
633}
634
635void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
636  DCHECK_EQ(SPDY_NO_ERROR, error_code_);
637  DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
638
639  if (control_frame_type_field < FIRST_CONTROL_TYPE ||
640      control_frame_type_field > LAST_CONTROL_TYPE) {
641    set_error(SPDY_INVALID_CONTROL_FRAME);
642    return;
643  }
644
645  current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
646
647  if (current_frame_type_ == NOOP) {
648    DLOG(INFO) << "NOOP control frame found. Ignoring.";
649    CHANGE_STATE(SPDY_AUTO_RESET);
650    return;
651  }
652
653  // Do some sanity checking on the control frame sizes and flags.
654  switch (current_frame_type_) {
655    case SYN_STREAM:
656      if (current_frame_length_ < GetSynStreamMinimumSize()) {
657        set_error(SPDY_INVALID_CONTROL_FRAME);
658      } else if (current_frame_flags_ &
659                 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
660        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
661      }
662      break;
663    case SYN_REPLY:
664      if (current_frame_length_ < GetSynReplyMinimumSize()) {
665        set_error(SPDY_INVALID_CONTROL_FRAME);
666      } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
667        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
668      }
669      break;
670    case RST_STREAM:
671      if (current_frame_length_ != GetRstStreamSize()) {
672        set_error(SPDY_INVALID_CONTROL_FRAME);
673      } else if (current_frame_flags_ != 0) {
674        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
675      }
676      break;
677    case SETTINGS:
678      // Make sure that we have an integral number of 8-byte key/value pairs,
679      // plus a 4-byte length field.
680      if (current_frame_length_ < GetSettingsMinimumSize() ||
681          (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) {
682        DLOG(WARNING) << "Invalid length for SETTINGS frame: "
683                      << current_frame_length_;
684        set_error(SPDY_INVALID_CONTROL_FRAME);
685      } else if (current_frame_flags_ &
686                 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
687        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
688      }
689      break;
690    case GOAWAY:
691      {
692        if (current_frame_length_ != GetGoAwaySize()) {
693          set_error(SPDY_INVALID_CONTROL_FRAME);
694        } else if (current_frame_flags_ != 0) {
695          set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
696        }
697        break;
698      }
699    case HEADERS:
700      if (current_frame_length_ < GetHeadersMinimumSize()) {
701        set_error(SPDY_INVALID_CONTROL_FRAME);
702      } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
703        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
704      }
705      break;
706    case WINDOW_UPDATE:
707      if (current_frame_length_ != GetWindowUpdateSize()) {
708        set_error(SPDY_INVALID_CONTROL_FRAME);
709      } else if (current_frame_flags_ != 0) {
710        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
711      }
712      break;
713    case PING:
714      if (current_frame_length_ != GetPingSize()) {
715        set_error(SPDY_INVALID_CONTROL_FRAME);
716      } else if (current_frame_flags_ != 0) {
717        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
718      }
719      break;
720    case CREDENTIAL:
721      if (current_frame_length_ < GetCredentialMinimumSize()) {
722        set_error(SPDY_INVALID_CONTROL_FRAME);
723      } else if (current_frame_flags_ != 0) {
724        set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
725      }
726      break;
727    default:
728      LOG(WARNING) << "Valid " << display_protocol_
729                   << " control frame with unhandled type: "
730                   << current_frame_type_;
731      // This branch should be unreachable because of the frame type bounds
732      // check above. However, we DLOG(FATAL) here in an effort to painfully
733      // club the head of the developer who failed to keep this file in sync
734      // with spdy_protocol.h.
735      DLOG(FATAL);
736      set_error(SPDY_INVALID_CONTROL_FRAME);
737      break;
738  }
739
740  if (state_ == SPDY_ERROR) {
741    return;
742  }
743
744  if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
745    DLOG(WARNING) << "Received control frame with way too big of a payload: "
746                  << current_frame_length_;
747    set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
748    return;
749  }
750
751  if (current_frame_type_ == CREDENTIAL) {
752    CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD);
753    return;
754  }
755
756  // Determine the frame size without variable-length data.
757  int32 frame_size_without_variable_data;
758  switch (current_frame_type_) {
759    case SYN_STREAM:
760      syn_frame_processed_ = true;
761      frame_size_without_variable_data = GetSynStreamMinimumSize();
762      break;
763    case SYN_REPLY:
764      syn_frame_processed_ = true;
765      frame_size_without_variable_data = GetSynReplyMinimumSize();
766      break;
767    case HEADERS:
768      frame_size_without_variable_data = GetHeadersMinimumSize();
769      break;
770    case SETTINGS:
771      frame_size_without_variable_data = GetSettingsMinimumSize();
772      break;
773    default:
774      frame_size_without_variable_data = -1;
775      break;
776  }
777
778  if ((frame_size_without_variable_data == -1) &&
779      (current_frame_length_ > kControlFrameBufferSize)) {
780    // We should already be in an error state. Double-check.
781    DCHECK_EQ(SPDY_ERROR, state_);
782    if (state_ != SPDY_ERROR) {
783      LOG(DFATAL) << display_protocol_
784                  << " control frame buffer too small for fixed-length frame.";
785      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
786    }
787    return;
788  }
789
790  if (frame_size_without_variable_data > 0) {
791    // We have a control frame with a header block. We need to parse the
792    // remainder of the control frame's header before we can parse the header
793    // block. The start of the header block varies with the control type.
794    DCHECK_GE(frame_size_without_variable_data,
795              static_cast<int32>(current_frame_buffer_length_));
796    remaining_control_header_ = frame_size_without_variable_data -
797        current_frame_buffer_length_;
798    CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
799    return;
800  }
801
802  CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
803}
804
805size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
806                                            size_t max_bytes) {
807  size_t bytes_to_read = std::min(*len, max_bytes);
808  DCHECK_GE(kControlFrameBufferSize,
809            current_frame_buffer_length_ + bytes_to_read);
810  memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
811         *data,
812         bytes_to_read);
813  current_frame_buffer_length_ += bytes_to_read;
814  *data += bytes_to_read;
815  *len -= bytes_to_read;
816  return bytes_to_read;
817}
818
819size_t SpdyFramer::GetSerializedLength(const int spdy_version,
820                                       const SpdyHeaderBlock* headers) {
821  const size_t num_name_value_pairs_size
822      = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32);
823  const size_t length_of_name_size = num_name_value_pairs_size;
824  const size_t length_of_value_size = num_name_value_pairs_size;
825
826  size_t total_length = num_name_value_pairs_size;
827  for (SpdyHeaderBlock::const_iterator it = headers->begin();
828       it != headers->end();
829       ++it) {
830    // We add space for the length of the name and the length of the value as
831    // well as the length of the name and the length of the value.
832    total_length += length_of_name_size + it->first.size() +
833                    length_of_value_size + it->second.size();
834  }
835  return total_length;
836}
837
838void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
839                                  const int spdy_version,
840                                  const SpdyHeaderBlock* headers) {
841  if (spdy_version < 3) {
842    frame->WriteUInt16(headers->size());  // Number of headers.
843  } else {
844    frame->WriteUInt32(headers->size());  // Number of headers.
845  }
846  SpdyHeaderBlock::const_iterator it;
847  for (it = headers->begin(); it != headers->end(); ++it) {
848    if (spdy_version < 3) {
849      frame->WriteString(it->first);
850      frame->WriteString(it->second);
851    } else {
852      frame->WriteStringPiece32(it->first);
853      frame->WriteStringPiece32(it->second);
854    }
855  }
856}
857
858// TODO(phajdan.jr): Clean up after we no longer need
859// to workaround http://crbug.com/139744.
860#if !defined(USE_SYSTEM_ZLIB)
861
862// These constants are used by zlib to differentiate between normal data and
863// cookie data. Cookie data is handled specially by zlib when compressing.
864enum ZDataClass {
865  // kZStandardData is compressed normally, save that it will never match
866  // against any other class of data in the window.
867  kZStandardData = Z_CLASS_STANDARD,
868  // kZCookieData is compressed in its own Huffman blocks and only matches in
869  // its entirety and only against other kZCookieData blocks. Any matches must
870  // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
871  // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
872  // prefix matches.
873  kZCookieData = Z_CLASS_COOKIE,
874  // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
875  // against the window.
876  kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
877};
878
879// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
880// needed when switching between classes of data.
881static void WriteZ(const base::StringPiece& data,
882                   ZDataClass clas,
883                   z_stream* out) {
884  int rv;
885
886  // If we are switching from standard to non-standard data then we need to end
887  // the current Huffman context to avoid it leaking between them.
888  if (out->clas == kZStandardData &&
889      clas != kZStandardData) {
890    out->avail_in = 0;
891    rv = deflate(out, Z_PARTIAL_FLUSH);
892    DCHECK_EQ(Z_OK, rv);
893    DCHECK_EQ(0u, out->avail_in);
894    DCHECK_LT(0u, out->avail_out);
895  }
896
897  out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
898  out->avail_in = data.size();
899  out->clas = clas;
900  if (clas == kZStandardData) {
901    rv = deflate(out, Z_NO_FLUSH);
902  } else {
903    rv = deflate(out, Z_PARTIAL_FLUSH);
904  }
905  if (!data.empty()) {
906    // If we didn't provide any data then zlib will return Z_BUF_ERROR.
907    DCHECK_EQ(Z_OK, rv);
908  }
909  DCHECK_EQ(0u, out->avail_in);
910  DCHECK_LT(0u, out->avail_out);
911}
912
913// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
914static void WriteLengthZ(size_t n,
915                         unsigned length,
916                         ZDataClass clas,
917                         z_stream* out) {
918  char buf[4];
919  DCHECK_LE(length, sizeof(buf));
920  for (unsigned i = 1; i <= length; i++) {
921    buf[length - i] = n;
922    n >>= 8;
923  }
924  WriteZ(base::StringPiece(buf, length), clas, out);
925}
926
927// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
928// manner that resists the length of the compressed data from compromising
929// cookie data.
930void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
931                                     z_stream* z) const {
932  unsigned length_length = 4;
933  if (spdy_version_ < 3)
934    length_length = 2;
935
936  WriteLengthZ(headers->size(), length_length, kZStandardData, z);
937
938  std::map<std::string, std::string>::const_iterator it;
939  for (it = headers->begin(); it != headers->end(); ++it) {
940    WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
941    WriteZ(it->first, kZStandardData, z);
942
943    if (it->first == "cookie") {
944      // We require the cookie values (save for the last) to end with a
945      // semicolon and (save for the first) to start with a space. This is
946      // typically the format that we are given them in but we reserialize them
947      // to be sure.
948
949      std::vector<base::StringPiece> cookie_values;
950      size_t cookie_length = 0;
951      base::StringPiece cookie_data(it->second);
952
953      for (;;) {
954        while (!cookie_data.empty() &&
955               (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
956          cookie_data.remove_prefix(1);
957        }
958        if (cookie_data.empty())
959          break;
960
961        size_t i;
962        for (i = 0; i < cookie_data.size(); i++) {
963          if (cookie_data[i] == ';')
964            break;
965        }
966        if (i < cookie_data.size()) {
967          cookie_values.push_back(cookie_data.substr(0, i));
968          cookie_length += i + 2 /* semicolon and space */;
969          cookie_data.remove_prefix(i + 1);
970        } else {
971          cookie_values.push_back(cookie_data);
972          cookie_length += cookie_data.size();
973          cookie_data.remove_prefix(i);
974        }
975      }
976
977      WriteLengthZ(cookie_length, length_length, kZStandardData, z);
978      for (size_t i = 0; i < cookie_values.size(); i++) {
979        std::string cookie;
980        // Since zlib will only back-reference complete cookies, a cookie that
981        // is currently last (and so doesn't have a trailing semicolon) won't
982        // match if it's later in a non-final position. The same is true of
983        // the first cookie.
984        if (i == 0 && cookie_values.size() == 1) {
985          cookie = cookie_values[i].as_string();
986        } else if (i == 0) {
987          cookie = cookie_values[i].as_string() + ";";
988        } else if (i < cookie_values.size() - 1) {
989          cookie = " " + cookie_values[i].as_string() + ";";
990        } else {
991          cookie = " " + cookie_values[i].as_string();
992        }
993        WriteZ(cookie, kZCookieData, z);
994      }
995    } else if (it->first == "accept" ||
996               it->first == "accept-charset" ||
997               it->first == "accept-encoding" ||
998               it->first == "accept-language" ||
999               it->first == "host" ||
1000               it->first == "version" ||
1001               it->first == "method" ||
1002               it->first == "scheme" ||
1003               it->first == ":host" ||
1004               it->first == ":version" ||
1005               it->first == ":method" ||
1006               it->first == ":scheme" ||
1007               it->first == "user-agent") {
1008      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1009      WriteZ(it->second, kZStandardData, z);
1010    } else {
1011      // Non-whitelisted headers are Huffman compressed in their own block, but
1012      // don't match against the window.
1013      WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1014      WriteZ(it->second, kZHuffmanOnlyData, z);
1015    }
1016  }
1017
1018  z->avail_in = 0;
1019  int rv = deflate(z, Z_SYNC_FLUSH);
1020  DCHECK_EQ(Z_OK, rv);
1021  z->clas = kZStandardData;
1022}
1023#endif  // !defined(USE_SYSTEM_ZLIB)
1024
1025size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1026                                                        size_t len) {
1027  DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1028  size_t original_len = len;
1029
1030  if (remaining_control_header_ > 0) {
1031    size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1032                                                 remaining_control_header_);
1033    remaining_control_header_ -= bytes_read;
1034    remaining_data_length_ -= bytes_read;
1035  }
1036
1037  if (remaining_control_header_ == 0) {
1038    SpdyFrameReader reader(current_frame_buffer_.get(),
1039                           current_frame_buffer_length_);
1040    reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
1041
1042    switch (current_frame_type_) {
1043      case SYN_STREAM:
1044        {
1045          bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1046          DCHECK(successful_read);
1047
1048          SpdyStreamId associated_to_stream_id = kInvalidStream;
1049          successful_read = reader.ReadUInt31(&associated_to_stream_id);
1050          DCHECK(successful_read);
1051
1052          SpdyPriority priority = 0;
1053          successful_read = reader.ReadUInt8(&priority);
1054          DCHECK(successful_read);
1055          if (protocol_version() < 3) {
1056            priority = priority >> 6;
1057          } else {
1058            priority = priority >> 5;
1059          }
1060
1061          uint8 slot = 0;
1062          if (protocol_version() < 3) {
1063            // SPDY 2 had an unused byte here. Seek past it.
1064            reader.Seek(1);
1065          } else {
1066            successful_read = reader.ReadUInt8(&slot);
1067            DCHECK(successful_read);
1068          }
1069
1070          DCHECK(reader.IsDoneReading());
1071          visitor_->OnSynStream(
1072              current_frame_stream_id_,
1073              associated_to_stream_id,
1074              priority,
1075              slot,
1076              (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1077              (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1078        }
1079        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1080        break;
1081      case SYN_REPLY:
1082      case HEADERS:
1083        // SYN_REPLY and HEADERS are the same, save for the visitor call.
1084        {
1085          bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1086          DCHECK(successful_read);
1087          if (protocol_version() < 3) {
1088            // SPDY 2 had two unused bytes here. Seek past them.
1089            reader.Seek(2);
1090          }
1091          DCHECK(reader.IsDoneReading());
1092          if (current_frame_type_ == SYN_REPLY) {
1093            visitor_->OnSynReply(
1094                current_frame_stream_id_,
1095                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1096          } else {
1097            visitor_->OnHeaders(
1098                current_frame_stream_id_,
1099                (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1100          }
1101        }
1102        CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1103        break;
1104      case SETTINGS:
1105        visitor_->OnSettings(current_frame_flags_ &
1106                             SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1107        CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1108        break;
1109      default:
1110        DCHECK(false);
1111    }
1112  }
1113  return original_len - len;
1114}
1115
1116// Does not buffer the control payload. Instead, either passes directly to the
1117// visitor or decompresses and then passes directly to the visitor, via
1118// IncrementallyDeliverControlFrameHeaderData() or
1119// IncrementallyDecompressControlFrameHeaderData() respectively.
1120size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1121                                                  size_t data_len) {
1122  DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1123
1124  bool processed_successfully = true;
1125  if (current_frame_type_ != SYN_STREAM &&
1126      current_frame_type_ != SYN_REPLY &&
1127      current_frame_type_ != HEADERS) {
1128    LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1129  }
1130  size_t process_bytes = std::min(data_len, remaining_data_length_);
1131  if (process_bytes > 0) {
1132    if (enable_compression_) {
1133      processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1134          current_frame_stream_id_, data, process_bytes);
1135    } else {
1136      processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1137          current_frame_stream_id_, data, process_bytes);
1138    }
1139
1140    remaining_data_length_ -= process_bytes;
1141  }
1142
1143  // Handle the case that there is no futher data in this frame.
1144  if (remaining_data_length_ == 0 && processed_successfully) {
1145    // The complete header block has been delivered. We send a zero-length
1146    // OnControlFrameHeaderData() to indicate this.
1147    visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1148
1149    // If this is a FIN, tell the caller.
1150    if (current_frame_flags_ & CONTROL_FLAG_FIN) {
1151      visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1152    }
1153
1154    CHANGE_STATE(SPDY_AUTO_RESET);
1155  }
1156
1157  // Handle error.
1158  if (!processed_successfully) {
1159    return data_len;
1160  }
1161
1162  // Return amount processed.
1163  return process_bytes;
1164}
1165
1166size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1167                                               size_t data_len) {
1168  DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1169  DCHECK_EQ(SETTINGS, current_frame_type_);
1170  size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1171  size_t processed_bytes = 0;
1172
1173  // Loop over our incoming data.
1174  while (unprocessed_bytes > 0) {
1175    // Process up to one setting at a time.
1176    size_t processing = std::min(
1177        unprocessed_bytes,
1178        static_cast<size_t>(8 - settings_scratch_.setting_buf_len));
1179
1180    // Check if we have a complete setting in our input.
1181    if (processing == 8) {
1182      // Parse the setting directly out of the input without buffering.
1183      if (!ProcessSetting(data + processed_bytes)) {
1184        set_error(SPDY_INVALID_CONTROL_FRAME);
1185        return processed_bytes;
1186      }
1187    } else {
1188      // Continue updating settings_scratch_.setting_buf.
1189      memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1190             data + processed_bytes,
1191             processing);
1192      settings_scratch_.setting_buf_len += processing;
1193
1194      // Check if we have a complete setting buffered.
1195      if (settings_scratch_.setting_buf_len == 8) {
1196        if (!ProcessSetting(settings_scratch_.setting_buf)) {
1197          set_error(SPDY_INVALID_CONTROL_FRAME);
1198          return processed_bytes;
1199        }
1200        // Reset settings_scratch_.setting_buf for our next setting.
1201        settings_scratch_.setting_buf_len = 0;
1202      }
1203    }
1204
1205    // Iterate.
1206    unprocessed_bytes -= processing;
1207    processed_bytes += processing;
1208  }
1209
1210  // Check if we're done handling this SETTINGS frame.
1211  remaining_data_length_ -= processed_bytes;
1212  if (remaining_data_length_ == 0) {
1213    CHANGE_STATE(SPDY_AUTO_RESET);
1214  }
1215
1216  return processed_bytes;
1217}
1218
1219bool SpdyFramer::ProcessSetting(const char* data) {
1220  // Extract fields.
1221  // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1222  const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1223  SettingsFlagsAndId id_and_flags =
1224      SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
1225  uint8 flags = id_and_flags.flags();
1226  uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1227
1228  // Validate id.
1229  switch (id_and_flags.id()) {
1230    case SETTINGS_UPLOAD_BANDWIDTH:
1231    case SETTINGS_DOWNLOAD_BANDWIDTH:
1232    case SETTINGS_ROUND_TRIP_TIME:
1233    case SETTINGS_MAX_CONCURRENT_STREAMS:
1234    case SETTINGS_CURRENT_CWND:
1235    case SETTINGS_DOWNLOAD_RETRANS_RATE:
1236    case SETTINGS_INITIAL_WINDOW_SIZE:
1237      // Valid values.
1238      break;
1239    default:
1240      DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
1241      return false;
1242  }
1243  SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());
1244
1245  // Detect duplciates.
1246  if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
1247    DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1248                  << " in " << display_protocol_ << " SETTINGS frame "
1249                  << "(last settikng id was "
1250                  << settings_scratch_.last_setting_id << ").";
1251    return false;
1252  }
1253  settings_scratch_.last_setting_id = id;
1254
1255  // Validate flags.
1256  uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1257  if ((flags & ~(kFlagsMask)) != 0) {
1258    DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1259                  << flags;
1260    return false;
1261  }
1262
1263  // Validation succeeded. Pass on to visitor.
1264  visitor_->OnSetting(id, flags, value);
1265  return true;
1266}
1267
1268size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1269  size_t original_len = len;
1270  if (remaining_data_length_) {
1271    size_t bytes_read =
1272        UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_);
1273    remaining_data_length_ -= bytes_read;
1274    if (remaining_data_length_ == 0) {
1275      SpdyFrameReader reader(current_frame_buffer_.get(),
1276                             current_frame_buffer_length_);
1277      reader.Seek(GetControlFrameHeaderSize());  // Skip frame header.
1278
1279      // Use frame-specific handlers.
1280      switch (current_frame_type_) {
1281        case PING: {
1282            SpdyPingId id = 0;
1283            bool successful_read = reader.ReadUInt32(&id);
1284            DCHECK(successful_read);
1285            DCHECK(reader.IsDoneReading());
1286            visitor_->OnPing(id);
1287          }
1288          break;
1289        case WINDOW_UPDATE: {
1290            uint32 delta_window_size = 0;
1291            bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1292            DCHECK(successful_read);
1293            successful_read = reader.ReadUInt31(&delta_window_size);
1294            DCHECK(successful_read);
1295            DCHECK(reader.IsDoneReading());
1296            visitor_->OnWindowUpdate(current_frame_stream_id_,
1297                                     delta_window_size);
1298          }
1299          break;
1300        case RST_STREAM: {
1301            bool successful_read = reader.ReadUInt32(&current_frame_stream_id_);
1302            DCHECK(successful_read);
1303            SpdyRstStreamStatus status = RST_STREAM_INVALID;
1304            uint32 status_raw = status;
1305            successful_read = reader.ReadUInt32(&status_raw);
1306            DCHECK(successful_read);
1307            if (status_raw > RST_STREAM_INVALID &&
1308                status_raw < RST_STREAM_NUM_STATUS_CODES) {
1309              status = static_cast<SpdyRstStreamStatus>(status_raw);
1310            } else {
1311              // TODO(hkhalil): Probably best to OnError here, depending on
1312              // our interpretation of the spec. Keeping with existing liberal
1313              // behavior for now.
1314            }
1315            DCHECK(reader.IsDoneReading());
1316            visitor_->OnRstStream(current_frame_stream_id_, status);
1317          }
1318          break;
1319        case GOAWAY: {
1320            bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1321            DCHECK(successful_read);
1322            SpdyGoAwayStatus status = GOAWAY_OK;
1323            if (spdy_version_ >= 3) {
1324              uint32 status_raw = GOAWAY_OK;
1325              successful_read = reader.ReadUInt32(&status_raw);
1326              DCHECK(successful_read);
1327              if (status_raw > static_cast<uint32>(GOAWAY_INVALID) &&
1328                  status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) {
1329                status = static_cast<SpdyGoAwayStatus>(status_raw);
1330              } else {
1331                // TODO(hkhalil): Probably best to OnError here, depending on
1332                // our interpretation of the spec. Keeping with existing liberal
1333                // behavior for now.
1334              }
1335            }
1336            DCHECK(reader.IsDoneReading());
1337            visitor_->OnGoAway(current_frame_stream_id_, status);
1338          }
1339          break;
1340        default:
1341          // Unreachable.
1342          LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1343      }
1344
1345      CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1346    }
1347  }
1348  return original_len - len;
1349}
1350
1351size_t SpdyFramer::ProcessCredentialFramePayload(const char* data, size_t len) {
1352  if (len > 0) {
1353    bool processed_succesfully = visitor_->OnCredentialFrameData(data, len);
1354    remaining_data_length_ -= len;
1355    if (!processed_succesfully) {
1356      set_error(SPDY_CREDENTIAL_FRAME_CORRUPT);
1357    } else if (remaining_data_length_ == 0) {
1358      visitor_->OnCredentialFrameData(NULL, 0);
1359      CHANGE_STATE(SPDY_AUTO_RESET);
1360    }
1361  }
1362  return len;
1363}
1364
1365size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
1366  size_t original_len = len;
1367
1368  if (remaining_data_length_ > 0) {
1369    size_t amount_to_forward = std::min(remaining_data_length_, len);
1370    if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
1371      // Only inform the visitor if there is data.
1372      if (amount_to_forward) {
1373        visitor_->OnStreamFrameData(
1374            current_frame_stream_id_, data, amount_to_forward, false);
1375      }
1376    }
1377    data += amount_to_forward;
1378    len -= amount_to_forward;
1379    remaining_data_length_ -= amount_to_forward;
1380
1381    // If the FIN flag is set, and there is no more data in this data
1382    // frame, inform the visitor of EOF via a 0-length data frame.
1383    if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
1384      visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1385    }
1386  }
1387
1388  if (remaining_data_length_ == 0) {
1389    CHANGE_STATE(SPDY_AUTO_RESET);
1390  }
1391  return original_len - len;
1392}
1393
1394size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
1395                                          size_t header_length,
1396                                          SpdyHeaderBlock* block) const {
1397  SpdyFrameReader reader(header_data, header_length);
1398
1399  // Read number of headers.
1400  uint32 num_headers;
1401  if (spdy_version_ < 3) {
1402    uint16 temp;
1403    if (!reader.ReadUInt16(&temp)) {
1404      DLOG(INFO) << "Unable to read number of headers.";
1405      return 0;
1406    }
1407    num_headers = temp;
1408  } else {
1409    if (!reader.ReadUInt32(&num_headers)) {
1410      DLOG(INFO) << "Unable to read number of headers.";
1411      return 0;
1412    }
1413  }
1414
1415  // Read each header.
1416  for (uint32 index = 0; index < num_headers; ++index) {
1417    base::StringPiece temp;
1418
1419    // Read header name.
1420    if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1421                            : !reader.ReadStringPiece32(&temp)) {
1422      DLOG(INFO) << "Unable to read header name (" << index + 1 << " of "
1423                 << num_headers << ").";
1424      return 0;
1425    }
1426    std::string name = temp.as_string();
1427
1428    // Read header value.
1429    if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1430                            : !reader.ReadStringPiece32(&temp)) {
1431      DLOG(INFO) << "Unable to read header value (" << index + 1 << " of "
1432                 << num_headers << ").";
1433      return 0;
1434    }
1435    std::string value = temp.as_string();
1436
1437    // Ensure no duplicates.
1438    if (block->find(name) != block->end()) {
1439      DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of "
1440                 << num_headers << ").";
1441      return 0;
1442    }
1443
1444    // Store header.
1445    (*block)[name] = value;
1446  }
1447  return reader.GetBytesConsumed();
1448}
1449
1450/* static */
1451bool SpdyFramer::ParseCredentialData(const char* data, size_t len,
1452                                     SpdyCredential* credential) {
1453  DCHECK(credential);
1454
1455  SpdyFrameReader parser(data, len);
1456  base::StringPiece temp;
1457  if (!parser.ReadUInt16(&credential->slot)) {
1458    return false;
1459  }
1460
1461  if (!parser.ReadStringPiece32(&temp)) {
1462    return false;
1463  }
1464  credential->proof = temp.as_string();
1465
1466  while (!parser.IsDoneReading()) {
1467    if (!parser.ReadStringPiece32(&temp)) {
1468      return false;
1469    }
1470    credential->certs.push_back(temp.as_string());
1471  }
1472  return true;
1473}
1474
1475SpdyFrame* SpdyFramer::CreateSynStream(
1476    SpdyStreamId stream_id,
1477    SpdyStreamId associated_stream_id,
1478    SpdyPriority priority,
1479    uint8 credential_slot,
1480    SpdyControlFlags flags,
1481    bool compressed,
1482    const SpdyHeaderBlock* headers) {
1483  DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL);
1484  DCHECK_EQ(enable_compression_, compressed);
1485
1486  SpdySynStreamIR syn_stream(stream_id);
1487  syn_stream.set_associated_to_stream_id(associated_stream_id);
1488  syn_stream.set_priority(priority);
1489  syn_stream.set_slot(credential_slot);
1490  syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
1491  syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1492  // TODO(hkhalil): Avoid copy here.
1493  *(syn_stream.GetMutableNameValueBlock()) = *headers;
1494
1495  scoped_ptr<SpdyFrame> syn_frame(SerializeSynStream(syn_stream));
1496  return syn_frame.release();
1497}
1498
1499SpdySerializedFrame* SpdyFramer::SerializeSynStream(
1500    const SpdySynStreamIR& syn_stream) {
1501  uint8 flags = 0;
1502  if (syn_stream.fin()) {
1503    flags |= CONTROL_FLAG_FIN;
1504  }
1505  if (syn_stream.unidirectional()) {
1506    flags |= CONTROL_FLAG_UNIDIRECTIONAL;
1507  }
1508
1509  // The size of this frame, including variable-length name-value block.
1510  const size_t size = GetSynStreamMinimumSize()
1511      + GetSerializedLength(syn_stream.name_value_block());
1512
1513  SpdyFrameBuilder builder(size);
1514  builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
1515  builder.WriteUInt32(syn_stream.stream_id());
1516  builder.WriteUInt32(syn_stream.associated_to_stream_id());
1517  uint8 priority = syn_stream.priority();
1518  if (priority > GetLowestPriority()) {
1519    DLOG(DFATAL) << "Priority out-of-bounds.";
1520    priority = GetLowestPriority();
1521  }
1522  builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
1523  builder.WriteUInt8(syn_stream.slot());
1524  DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
1525  SerializeNameValueBlock(&builder, syn_stream);
1526
1527  if (visitor_)
1528    visitor_->OnSynStreamCompressed(size, builder.length());
1529
1530  return builder.take();
1531}
1532
1533SpdyFrame* SpdyFramer::CreateSynReply(
1534    SpdyStreamId stream_id,
1535    SpdyControlFlags flags,
1536    bool compressed,
1537    const SpdyHeaderBlock* headers) {
1538  DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN);
1539  DCHECK_EQ(enable_compression_, compressed);
1540
1541  SpdySynReplyIR syn_reply(stream_id);
1542  syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
1543  // TODO(hkhalil): Avoid copy here.
1544  *(syn_reply.GetMutableNameValueBlock()) = *headers;
1545
1546  scoped_ptr<SpdyFrame> reply_frame(SerializeSynReply(syn_reply));
1547  return reply_frame.release();
1548}
1549
1550SpdySerializedFrame* SpdyFramer::SerializeSynReply(
1551    const SpdySynReplyIR& syn_reply) {
1552  uint8 flags = 0;
1553  if (syn_reply.fin()) {
1554    flags |= CONTROL_FLAG_FIN;
1555  }
1556
1557  // The size of this frame, including variable-length name-value block.
1558  size_t size = GetSynReplyMinimumSize()
1559      + GetSerializedLength(syn_reply.name_value_block());
1560
1561  SpdyFrameBuilder builder(size);
1562  builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
1563  builder.WriteUInt32(syn_reply.stream_id());
1564  if (protocol_version() < 3) {
1565    builder.WriteUInt16(0);  // Unused.
1566  }
1567  DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
1568  SerializeNameValueBlock(&builder, syn_reply);
1569
1570  return builder.take();
1571}
1572
1573SpdyFrame* SpdyFramer::CreateRstStream(
1574    SpdyStreamId stream_id,
1575    SpdyRstStreamStatus status) const {
1576  SpdyRstStreamIR rst_stream(stream_id, status);
1577  return SerializeRstStream(rst_stream);
1578}
1579
1580SpdySerializedFrame* SpdyFramer::SerializeRstStream(
1581    const SpdyRstStreamIR& rst_stream) const {
1582  SpdyFrameBuilder builder(GetRstStreamSize());
1583  builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
1584  builder.WriteUInt32(rst_stream.stream_id());
1585  builder.WriteUInt32(rst_stream.status());
1586  DCHECK_EQ(GetRstStreamSize(), builder.length());
1587  return builder.take();
1588}
1589
1590SpdyFrame* SpdyFramer::CreateSettings(
1591    const SettingsMap& values) const {
1592  SpdySettingsIR settings;
1593  for (SettingsMap::const_iterator it = values.begin();
1594       it != values.end();
1595       ++it) {
1596    settings.AddSetting(it->first,
1597                        (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
1598                        (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
1599                        it->second.second);
1600  }
1601  return SerializeSettings(settings);
1602}
1603
1604SpdySerializedFrame* SpdyFramer::SerializeSettings(
1605    const SpdySettingsIR& settings) const {
1606  uint8 flags = 0;
1607  if (settings.clear_settings()) {
1608    flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1609  }
1610  const SpdySettingsIR::ValueMap* values = &(settings.values());
1611
1612  // Size, in bytes, of this SETTINGS frame.
1613  const size_t size = GetSettingsMinimumSize() + (values->size() * 8);
1614
1615  SpdyFrameBuilder builder(size);
1616  builder.WriteControlFrameHeader(*this, SETTINGS, flags);
1617  builder.WriteUInt32(values->size());
1618  DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
1619  for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
1620       it != values->end();
1621       ++it) {
1622    uint8 setting_flags = 0;
1623    if (it->second.persist_value) {
1624      setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
1625    }
1626    if (it->second.persisted) {
1627      setting_flags |= SETTINGS_FLAG_PERSISTED;
1628    }
1629    SettingsFlagsAndId flags_and_id(setting_flags, it->first);
1630    uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
1631    builder.WriteBytes(&id_and_flags_wire, 4);
1632    builder.WriteUInt32(it->second.value);
1633  }
1634  DCHECK_EQ(size, builder.length());
1635  return builder.take();
1636}
1637
1638SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const {
1639  SpdyPingIR ping(unique_id);
1640  return SerializePing(ping);
1641}
1642
1643SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
1644  SpdyFrameBuilder builder(GetPingSize());
1645  builder.WriteControlFrameHeader(*this, PING, 0);
1646  builder.WriteUInt32(ping.id());
1647  DCHECK_EQ(GetPingSize(), builder.length());
1648  return builder.take();
1649}
1650
1651SpdyFrame* SpdyFramer::CreateGoAway(
1652    SpdyStreamId last_accepted_stream_id,
1653    SpdyGoAwayStatus status) const {
1654  SpdyGoAwayIR goaway(last_accepted_stream_id, status);
1655  return SerializeGoAway(goaway);
1656}
1657
1658SpdySerializedFrame* SpdyFramer::SerializeGoAway(
1659    const SpdyGoAwayIR& goaway) const {
1660  SpdyFrameBuilder builder(GetGoAwaySize());
1661  builder.WriteControlFrameHeader(*this, GOAWAY, 0);
1662  builder.WriteUInt32(goaway.last_good_stream_id());
1663  if (protocol_version() >= 3) {
1664    builder.WriteUInt32(goaway.status());
1665  }
1666  DCHECK_EQ(GetGoAwaySize(), builder.length());
1667  return builder.take();
1668}
1669
1670SpdyFrame* SpdyFramer::CreateHeaders(
1671    SpdyStreamId stream_id,
1672    SpdyControlFlags flags,
1673    bool compressed,
1674    const SpdyHeaderBlock* header_block) {
1675  // Basically the same as CreateSynReply().
1676  DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN));
1677  DCHECK_EQ(enable_compression_, compressed);
1678
1679  SpdyHeadersIR headers(stream_id);
1680  headers.set_fin(flags & CONTROL_FLAG_FIN);
1681  // TODO(hkhalil): Avoid copy here.
1682  *(headers.GetMutableNameValueBlock()) = *header_block;
1683
1684  scoped_ptr<SpdyFrame> headers_frame(SerializeHeaders(headers));
1685  return headers_frame.release();
1686}
1687
1688SpdySerializedFrame* SpdyFramer::SerializeHeaders(
1689    const SpdyHeadersIR& headers) {
1690  uint8 flags = 0;
1691  if (headers.fin()) {
1692    flags |= CONTROL_FLAG_FIN;
1693  }
1694
1695  // The size of this frame, including variable-length name-value block.
1696  size_t size = GetHeadersMinimumSize()
1697      + GetSerializedLength(headers.name_value_block());
1698
1699  SpdyFrameBuilder builder(size);
1700  builder.WriteControlFrameHeader(*this, HEADERS, flags);
1701  builder.WriteUInt32(headers.stream_id());
1702  if (protocol_version() < 3) {
1703    builder.WriteUInt16(0);  // Unused.
1704  }
1705  DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
1706
1707  SerializeNameValueBlock(&builder, headers);
1708
1709  return builder.take();
1710}
1711
1712SpdyFrame* SpdyFramer::CreateWindowUpdate(
1713    SpdyStreamId stream_id,
1714    uint32 delta_window_size) const {
1715  SpdyWindowUpdateIR window_update(stream_id, delta_window_size);
1716  return SerializeWindowUpdate(window_update);
1717}
1718
1719SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
1720    const SpdyWindowUpdateIR& window_update) const {
1721  SpdyFrameBuilder builder(GetWindowUpdateSize());
1722  builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
1723  builder.WriteUInt32(window_update.stream_id());
1724  builder.WriteUInt32(window_update.delta());
1725  DCHECK_EQ(GetWindowUpdateSize(), builder.length());
1726  return builder.take();
1727}
1728
1729// TODO(hkhalil): Gut with SpdyCredential removal.
1730SpdyFrame* SpdyFramer::CreateCredentialFrame(
1731    const SpdyCredential& credential) const {
1732  SpdyCredentialIR credential_ir(credential.slot);
1733  credential_ir.set_proof(credential.proof);
1734  for (std::vector<std::string>::const_iterator cert = credential.certs.begin();
1735       cert != credential.certs.end();
1736       ++cert) {
1737    credential_ir.AddCertificate(*cert);
1738  }
1739  return SerializeCredential(credential_ir);
1740}
1741
1742SpdySerializedFrame* SpdyFramer::SerializeCredential(
1743    const SpdyCredentialIR& credential) const {
1744  size_t size = GetCredentialMinimumSize();
1745  size += 4 + credential.proof().length();  // Room for proof.
1746  for (SpdyCredentialIR::CertificateList::const_iterator it =
1747       credential.certificates()->begin();
1748       it != credential.certificates()->end();
1749       ++it) {
1750    size += 4 + it->length();  // Room for certificate.
1751  }
1752
1753  SpdyFrameBuilder builder(size);
1754  builder.WriteControlFrameHeader(*this, CREDENTIAL, 0);
1755  builder.WriteUInt16(credential.slot());
1756  DCHECK_EQ(GetCredentialMinimumSize(), builder.length());
1757  builder.WriteStringPiece32(credential.proof());
1758  for (SpdyCredentialIR::CertificateList::const_iterator it =
1759       credential.certificates()->begin();
1760       it != credential.certificates()->end();
1761       ++it) {
1762    builder.WriteStringPiece32(*it);
1763  }
1764  DCHECK_EQ(size, builder.length());
1765  return builder.take();
1766}
1767
1768SpdyFrame* SpdyFramer::CreateDataFrame(
1769    SpdyStreamId stream_id, const char* data,
1770    uint32 len, SpdyDataFlags flags) const {
1771  DCHECK_EQ(0, flags & (!DATA_FLAG_FIN));
1772
1773  SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
1774  data_ir.set_fin(flags & DATA_FLAG_FIN);
1775  return SerializeData(data_ir);
1776}
1777
1778SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
1779  const size_t kSize = GetDataFrameMinimumSize() + data.data().length();
1780
1781  SpdyDataFlags flags = DATA_FLAG_NONE;
1782  if (data.fin()) {
1783    flags = DATA_FLAG_FIN;
1784  }
1785
1786  SpdyFrameBuilder builder(kSize);
1787  builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1788  builder.WriteBytes(data.data().data(), data.data().length());
1789  DCHECK_EQ(kSize, builder.length());
1790  return builder.take();
1791}
1792
1793SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
1794    const SpdyDataIR& data) const {
1795  const size_t kSize = GetDataFrameMinimumSize();
1796
1797  SpdyDataFlags flags = DATA_FLAG_NONE;
1798  if (data.fin()) {
1799    flags = DATA_FLAG_FIN;
1800  }
1801
1802  SpdyFrameBuilder builder(kSize);
1803  builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1804  if (protocol_version() < 4) {
1805    builder.OverwriteLength(*this, data.data().length());
1806  } else {
1807    builder.OverwriteLength(*this, data.data().length() + kSize);
1808  }
1809  DCHECK_EQ(kSize, builder.length());
1810  return builder.take();
1811}
1812
1813size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
1814  const size_t uncompressed_length =
1815      GetSerializedLength(protocol_version(), &headers);
1816  if (!enable_compression_) {
1817    return uncompressed_length;
1818  }
1819  z_stream* compressor = GetHeaderCompressor();
1820  // Since we'll be performing lots of flushes when compressing the data,
1821  // zlib's lower bounds may be insufficient.
1822  return 2 * deflateBound(compressor, uncompressed_length);
1823}
1824
1825// The following compression setting are based on Brian Olson's analysis. See
1826// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
1827// for more details.
1828#if defined(USE_SYSTEM_ZLIB)
1829// System zlib is not expected to have workaround for http://crbug.com/139744,
1830// so disable compression in that case.
1831// TODO(phajdan.jr): Remove the special case when it's no longer necessary.
1832static const int kCompressorLevel = 0;
1833#else  // !defined(USE_SYSTEM_ZLIB)
1834static const int kCompressorLevel = 9;
1835#endif  // !defined(USE_SYSTEM_ZLIB)
1836static const int kCompressorWindowSizeInBits = 11;
1837static const int kCompressorMemLevel = 1;
1838
1839z_stream* SpdyFramer::GetHeaderCompressor() {
1840  if (header_compressor_.get())
1841    return header_compressor_.get();  // Already initialized.
1842
1843  header_compressor_.reset(new z_stream);
1844  memset(header_compressor_.get(), 0, sizeof(z_stream));
1845
1846  int success = deflateInit2(header_compressor_.get(),
1847                             kCompressorLevel,
1848                             Z_DEFLATED,
1849                             kCompressorWindowSizeInBits,
1850                             kCompressorMemLevel,
1851                             Z_DEFAULT_STRATEGY);
1852  if (success == Z_OK) {
1853    const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
1854                                                 : kV3Dictionary;
1855    const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
1856                                                    : kV3DictionarySize;
1857    success = deflateSetDictionary(header_compressor_.get(),
1858                                   reinterpret_cast<const Bytef*>(dictionary),
1859                                   dictionary_size);
1860  }
1861  if (success != Z_OK) {
1862    LOG(WARNING) << "deflateSetDictionary failure: " << success;
1863    header_compressor_.reset(NULL);
1864    return NULL;
1865  }
1866  return header_compressor_.get();
1867}
1868
1869z_stream* SpdyFramer::GetHeaderDecompressor() {
1870  if (header_decompressor_.get())
1871    return header_decompressor_.get();  // Already initialized.
1872
1873  header_decompressor_.reset(new z_stream);
1874  memset(header_decompressor_.get(), 0, sizeof(z_stream));
1875
1876  int success = inflateInit(header_decompressor_.get());
1877  if (success != Z_OK) {
1878    LOG(WARNING) << "inflateInit failure: " << success;
1879    header_decompressor_.reset(NULL);
1880    return NULL;
1881  }
1882  return header_decompressor_.get();
1883}
1884
1885// Incrementally decompress the control frame's header block, feeding the
1886// result to the visitor in chunks. Continue this until the visitor
1887// indicates that it cannot process any more data, or (more commonly) we
1888// run out of data to deliver.
1889bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
1890    SpdyStreamId stream_id,
1891    const char* data,
1892    size_t len) {
1893  // Get a decompressor or set error.
1894  z_stream* decomp = GetHeaderDecompressor();
1895  if (decomp == NULL) {
1896    LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
1897    set_error(SPDY_DECOMPRESS_FAILURE);
1898    return false;
1899  }
1900
1901  bool processed_successfully = true;
1902  char buffer[kHeaderDataChunkMaxSize];
1903
1904  decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
1905  decomp->avail_in = len;
1906  DCHECK_LT(0u, stream_id);
1907  while (decomp->avail_in > 0 && processed_successfully) {
1908    decomp->next_out = reinterpret_cast<Bytef*>(buffer);
1909    decomp->avail_out = arraysize(buffer);
1910
1911    int rv = inflate(decomp, Z_SYNC_FLUSH);
1912    if (rv == Z_NEED_DICT) {
1913      const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
1914                                                   : kV3Dictionary;
1915      const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
1916                                                      : kV3DictionarySize;
1917      const DictionaryIds& ids = g_dictionary_ids.Get();
1918      const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
1919                                                      : ids.v3_dictionary_id;
1920      // Need to try again with the right dictionary.
1921      if (decomp->adler == dictionary_id) {
1922        rv = inflateSetDictionary(decomp,
1923                                  reinterpret_cast<const Bytef*>(dictionary),
1924                                  dictionary_size);
1925        if (rv == Z_OK)
1926          rv = inflate(decomp, Z_SYNC_FLUSH);
1927      }
1928    }
1929
1930    // Inflate will generate a Z_BUF_ERROR if it runs out of input
1931    // without producing any output.  The input is consumed and
1932    // buffered internally by zlib so we can detect this condition by
1933    // checking if avail_in is 0 after the call to inflate.
1934    bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
1935    if ((rv == Z_OK) || input_exhausted) {
1936      size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
1937      if (debug_visitor_ != NULL) {
1938        debug_visitor_->OnDecompressedHeaderBlock(decompressed_len, len);
1939      }
1940      if (decompressed_len > 0) {
1941        processed_successfully = visitor_->OnControlFrameHeaderData(
1942            stream_id, buffer, decompressed_len);
1943      }
1944      if (!processed_successfully) {
1945        // Assume that the problem was the header block was too large for the
1946        // visitor.
1947        set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1948      }
1949    } else {
1950      DLOG(WARNING) << "inflate failure: " << rv << " " << len;
1951      set_error(SPDY_DECOMPRESS_FAILURE);
1952      processed_successfully = false;
1953    }
1954  }
1955  return processed_successfully;
1956}
1957
1958bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
1959    SpdyStreamId stream_id, const char* data, size_t len) {
1960  bool read_successfully = true;
1961  while (read_successfully && len > 0) {
1962    size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
1963    read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
1964                                                           bytes_to_deliver);
1965    data += bytes_to_deliver;
1966    len -= bytes_to_deliver;
1967    if (!read_successfully) {
1968      // Assume that the problem was the header block was too large for the
1969      // visitor.
1970      set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1971    }
1972  }
1973  return read_successfully;
1974}
1975
1976void SpdyFramer::SerializeNameValueBlockWithoutCompression(
1977    SpdyFrameBuilder* builder,
1978    const SpdyNameValueBlock& name_value_block) const {
1979  // Serialize number of headers.
1980  if (protocol_version() < 3) {
1981    builder->WriteUInt16(name_value_block.size());
1982  } else {
1983    builder->WriteUInt32(name_value_block.size());
1984  }
1985
1986  // Serialize each header.
1987  for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
1988       it != name_value_block.end();
1989       ++it) {
1990    if (protocol_version() < 3) {
1991      builder->WriteString(it->first);
1992      builder->WriteString(it->second);
1993    } else {
1994      builder->WriteStringPiece32(it->first);
1995      builder->WriteStringPiece32(it->second);
1996    }
1997  }
1998}
1999
2000void SpdyFramer::SerializeNameValueBlock(
2001    SpdyFrameBuilder* builder,
2002    const SpdyFrameWithNameValueBlockIR& frame) {
2003  if (!enable_compression_) {
2004    return SerializeNameValueBlockWithoutCompression(builder,
2005                                                     frame.name_value_block());
2006  }
2007
2008  // First build an uncompressed version to be fed into the compressor.
2009  const size_t uncompressed_len = GetSerializedLength(
2010      protocol_version(), &(frame.name_value_block()));
2011  SpdyFrameBuilder uncompressed_builder(uncompressed_len);
2012  SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
2013                                            frame.name_value_block());
2014  scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
2015
2016  z_stream* compressor = GetHeaderCompressor();
2017  if (!compressor) {
2018    LOG(DFATAL) << "Could not obtain compressor.";
2019    return;
2020  }
2021
2022  base::StatsCounter compressed_frames("spdy.CompressedFrames");
2023  base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
2024  base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
2025
2026  // Create an output frame.
2027  // Since we'll be performing lots of flushes when compressing the data,
2028  // zlib's lower bounds may be insufficient.
2029  //
2030  // TODO(akalin): Avoid the duplicate calculation with
2031  // GetSerializedLength(const SpdyHeaderBlock&).
2032  const int compressed_max_size =
2033      2 * deflateBound(compressor, uncompressed_len);
2034
2035  // TODO(phajdan.jr): Clean up after we no longer need
2036  // to workaround http://crbug.com/139744.
2037#if defined(USE_SYSTEM_ZLIB)
2038  compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
2039  compressor->avail_in = uncompressed_len;
2040#endif  // defined(USE_SYSTEM_ZLIB)
2041  compressor->next_out = reinterpret_cast<Bytef*>(
2042      builder->GetWritableBuffer(compressed_max_size));
2043  compressor->avail_out = compressed_max_size;
2044
2045  // TODO(phajdan.jr): Clean up after we no longer need
2046  // to workaround http://crbug.com/139744.
2047#if defined(USE_SYSTEM_ZLIB)
2048  int rv = deflate(compressor, Z_SYNC_FLUSH);
2049  if (rv != Z_OK) {  // How can we know that it compressed everything?
2050    // This shouldn't happen, right?
2051    LOG(WARNING) << "deflate failure: " << rv;
2052    // TODO(akalin): Upstream this return.
2053    return;
2054  }
2055#else
2056  WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
2057#endif  // defined(USE_SYSTEM_ZLIB)
2058
2059  int compressed_size = compressed_max_size - compressor->avail_out;
2060  builder->Seek(compressed_size);
2061  builder->RewriteLength(*this);
2062
2063  pre_compress_bytes.Add(uncompressed_len);
2064  post_compress_bytes.Add(compressed_size);
2065
2066  compressed_frames.Increment();
2067
2068  if (debug_visitor_ != NULL) {
2069    debug_visitor_->OnCompressedHeaderBlock(uncompressed_len, compressed_size);
2070  }
2071}
2072
2073}  // namespace net
2074