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