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