Home | History | Annotate | Download | only in spdy
      1 // Copyright (c) 2011 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/memory/scoped_ptr.h"
     12 #include "base/metrics/stats_counters.h"
     13 #ifndef ANDROID
     14 #include "base/third_party/valgrind/memcheck.h"
     15 #endif
     16 #include "net/spdy/spdy_frame_builder.h"
     17 #include "net/spdy/spdy_bitmasks.h"
     18 
     19 #if defined(USE_SYSTEM_ZLIB)
     20 #include <zlib.h>
     21 #else
     22 #include "third_party/zlib/zlib.h"
     23 #endif
     24 
     25 namespace {
     26 
     27 // The following compression setting are based on Brian Olson's analysis. See
     28 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
     29 // for more details.
     30 const int kCompressorLevel = 9;
     31 const int kCompressorWindowSizeInBits = 11;
     32 const int kCompressorMemLevel = 1;
     33 
     34 // Adler ID for the SPDY header compressor dictionary.
     35 uLong dictionary_id = 0;
     36 
     37 }  // namespace
     38 
     39 namespace spdy {
     40 
     41 // This is just a hacked dictionary to use for shrinking HTTP-like headers.
     42 // TODO(mbelshe): Use a scientific methodology for computing the dictionary.
     43 const char SpdyFramer::kDictionary[] =
     44   "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
     45   "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
     46   "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
     47   "-agent10010120020120220320420520630030130230330430530630740040140240340440"
     48   "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
     49   "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
     50   "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
     51   "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
     52   "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
     53   "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
     54   "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
     55   "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
     56   ".1statusversionurl";
     57 const int SpdyFramer::kDictionarySize = arraysize(kDictionary);
     58 
     59 // By default is compression on or off.
     60 bool SpdyFramer::compression_default_ = true;
     61 int SpdyFramer::spdy_version_ = kSpdyProtocolVersion;
     62 
     63 // The initial size of the control frame buffer; this is used internally
     64 // as we parse through control frames. (It is exposed here for unit test
     65 // purposes.)
     66 size_t SpdyFramer::kControlFrameBufferInitialSize = 8 * 1024;
     67 
     68 // The maximum size of the control frame buffer that we support.
     69 // TODO(mbelshe): We should make this stream-based so there are no limits.
     70 size_t SpdyFramer::kControlFrameBufferMaxSize = 16 * 1024;
     71 
     72 const SpdyStreamId SpdyFramer::kInvalidStream = -1;
     73 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
     74 
     75 #ifdef DEBUG_SPDY_STATE_CHANGES
     76 #define CHANGE_STATE(newstate) \
     77 { \
     78   do { \
     79     LOG(INFO) << "Changing state from: " \
     80       << StateToString(state_) \
     81       << " to " << StateToString(newstate) << "\n"; \
     82     state_ = newstate; \
     83   } while (false); \
     84 }
     85 #else
     86 #define CHANGE_STATE(newstate) (state_ = newstate)
     87 #endif
     88 
     89 int DecompressHeaderBlockInZStream(z_stream* decompressor) {
     90   int rv = inflate(decompressor, Z_SYNC_FLUSH);
     91   if (rv == Z_NEED_DICT) {
     92     // Need to try again with the right dictionary.
     93     if (decompressor->adler == dictionary_id) {
     94       rv = inflateSetDictionary(decompressor,
     95                                 (const Bytef*)SpdyFramer::kDictionary,
     96                                 SpdyFramer::kDictionarySize);
     97       if (rv == Z_OK)
     98         rv = inflate(decompressor, Z_SYNC_FLUSH);
     99     }
    100   }
    101   return rv;
    102 }
    103 
    104 // Retrieve serialized length of SpdyHeaderBlock.
    105 size_t GetSerializedLength(const SpdyHeaderBlock* headers) {
    106   size_t total_length = SpdyControlFrame::kNumNameValuePairsSize;
    107   SpdyHeaderBlock::const_iterator it;
    108   for (it = headers->begin(); it != headers->end(); ++it) {
    109     // We add space for the length of the name and the length of the value as
    110     // well as the length of the name and the length of the value.
    111     total_length += SpdyControlFrame::kLengthOfNameSize +
    112                     it->first.size() +
    113                     SpdyControlFrame::kLengthOfValueSize +
    114                     it->second.size();
    115   }
    116   return total_length;
    117 }
    118 
    119 // Serializes a SpdyHeaderBlock.
    120 void WriteHeaderBlock(SpdyFrameBuilder* frame, const SpdyHeaderBlock* headers) {
    121   frame->WriteUInt16(headers->size());  // Number of headers.
    122   SpdyHeaderBlock::const_iterator it;
    123   for (it = headers->begin(); it != headers->end(); ++it) {
    124     bool wrote_header;
    125     wrote_header = frame->WriteString(it->first);
    126     wrote_header &= frame->WriteString(it->second);
    127     DCHECK(wrote_header);
    128   }
    129 }
    130 
    131 // Creates a FlagsAndLength.
    132 FlagsAndLength CreateFlagsAndLength(SpdyControlFlags flags, size_t length) {
    133   DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
    134   FlagsAndLength flags_length;
    135   flags_length.length_ = htonl(static_cast<uint32>(length));
    136   DCHECK_EQ(0, flags & ~kControlFlagsMask);
    137   flags_length.flags_[0] = flags;
    138   return flags_length;
    139 }
    140 
    141 SpdyFramer::SpdyFramer()
    142     : state_(SPDY_RESET),
    143       error_code_(SPDY_NO_ERROR),
    144       remaining_data_(0),
    145       remaining_control_payload_(0),
    146       remaining_control_header_(0),
    147       current_frame_buffer_(NULL),
    148       current_frame_len_(0),
    149       current_frame_capacity_(0),
    150       validate_control_frame_sizes_(true),
    151       enable_compression_(compression_default_),
    152       visitor_(NULL) {
    153 }
    154 
    155 SpdyFramer::~SpdyFramer() {
    156   if (header_compressor_.get()) {
    157     deflateEnd(header_compressor_.get());
    158   }
    159   if (header_decompressor_.get()) {
    160     inflateEnd(header_decompressor_.get());
    161   }
    162   CleanupStreamCompressorsAndDecompressors();
    163   delete [] current_frame_buffer_;
    164 }
    165 
    166 const char* SpdyFramer::StatusCodeToString(int status_code) {
    167   switch (status_code) {
    168     case INVALID:
    169       return "INVALID";
    170     case PROTOCOL_ERROR:
    171       return "PROTOCOL_ERROR";
    172     case INVALID_STREAM:
    173       return "INVALID_STREAM";
    174     case REFUSED_STREAM:
    175       return "REFUSED_STREAM";
    176     case UNSUPPORTED_VERSION:
    177       return "UNSUPPORTED_VERSION";
    178     case CANCEL:
    179       return "CANCEL";
    180     case INTERNAL_ERROR:
    181       return "INTERNAL_ERROR";
    182     case FLOW_CONTROL_ERROR:
    183       return "FLOW_CONTROL_ERROR";
    184   }
    185   return "UNKNOWN_STATUS";
    186 }
    187 
    188 const char* SpdyFramer::ControlTypeToString(SpdyControlType type) {
    189   switch (type) {
    190     case SYN_STREAM:
    191       return "SYN_STREAM";
    192     case SYN_REPLY:
    193       return "SYN_REPLY";
    194     case RST_STREAM:
    195       return "RST_STREAM";
    196     case SETTINGS:
    197       return "SETTINGS";
    198     case NOOP:
    199       return "NOOP";
    200     case PING:
    201       return "PING";
    202     case GOAWAY:
    203       return "GOAWAY";
    204     case HEADERS:
    205       return "HEADERS";
    206     case WINDOW_UPDATE:
    207       return "WINDOW_UPDATE";
    208     case NUM_CONTROL_FRAME_TYPES:
    209       break;
    210   }
    211   return "UNKNOWN_CONTROL_TYPE";
    212 }
    213 
    214 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
    215   DCHECK(visitor_);
    216   DCHECK(data);
    217 
    218   size_t original_len = len;
    219   while (len != 0) {
    220     switch (state_) {
    221       case SPDY_ERROR:
    222       case SPDY_DONE:
    223         goto bottom;
    224 
    225       case SPDY_AUTO_RESET:
    226       case SPDY_RESET:
    227         Reset();
    228         CHANGE_STATE(SPDY_READING_COMMON_HEADER);
    229         continue;
    230 
    231       case SPDY_READING_COMMON_HEADER: {
    232         size_t bytes_read = ProcessCommonHeader(data, len);
    233         len -= bytes_read;
    234         data += bytes_read;
    235         continue;
    236       }
    237 
    238       // Arguably, this case is not necessary, as no bytes are consumed here.
    239       // I felt it was a nice partitioning, however (which probably indicates
    240       // that it should be refactored into its own function!)
    241       // TODO(hkhalil): Remove -- while loop above prevents proper handling of
    242       // zero-length control frames.
    243       case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
    244         ProcessControlFrameHeader();
    245         continue;
    246 
    247       case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
    248         // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY,
    249         // HEADERS) take a different path through the state machine - they
    250         // will go:
    251         //   1. SPDY_INTERPRET_CONTROL_FRAME_COMMON HEADER
    252         //   2. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
    253         //   3. SPDY_CONTROL_FRAME_HEADER_BLOCK
    254         //
    255         //  All other control frames will use the alternate route:
    256         //   1. SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER
    257         //   2. SPDY_CONTROL_FRAME_PAYLOAD
    258         int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
    259         len -= bytes_read;
    260         data += bytes_read;
    261         continue;
    262       }
    263 
    264       case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
    265         int bytes_read = ProcessControlFrameHeaderBlock(data, len);
    266         len -= bytes_read;
    267         data += bytes_read;
    268         continue;
    269       }
    270 
    271       case SPDY_CONTROL_FRAME_PAYLOAD: {
    272         size_t bytes_read = ProcessControlFramePayload(data, len);
    273         len -= bytes_read;
    274         data += bytes_read;
    275       }
    276         // intentional fallthrough
    277       case SPDY_IGNORE_REMAINING_PAYLOAD:
    278         // control frame has too-large payload
    279         // intentional fallthrough
    280       case SPDY_FORWARD_STREAM_FRAME: {
    281         size_t bytes_read = ProcessDataFramePayload(data, len);
    282         len -= bytes_read;
    283         data += bytes_read;
    284         continue;
    285       }
    286       default:
    287         break;
    288     }
    289   }
    290  bottom:
    291   return original_len - len;
    292 }
    293 
    294 void SpdyFramer::Reset() {
    295   state_ = SPDY_RESET;
    296   error_code_ = SPDY_NO_ERROR;
    297   remaining_data_ = 0;
    298   remaining_control_payload_ = 0;
    299   remaining_control_header_ = 0;
    300   current_frame_len_ = 0;
    301   if (current_frame_capacity_ != kControlFrameBufferInitialSize) {
    302     delete [] current_frame_buffer_;
    303     current_frame_buffer_ = 0;
    304     current_frame_capacity_ = 0;
    305     ExpandControlFrameBuffer(kControlFrameBufferInitialSize);
    306   }
    307 }
    308 
    309 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame,
    310                                   SpdyHeaderBlock* block) {
    311   SpdyControlFrame control_frame(frame->data(), false);
    312   uint32 type = control_frame.type();
    313   if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS)
    314     return false;
    315 
    316   // Find the header data within the control frame.
    317   scoped_ptr<SpdyFrame> decompressed_frame(DecompressFrame(*frame));
    318   if (!decompressed_frame.get())
    319     return false;
    320 
    321   const char *header_data = NULL;
    322   int header_length = 0;
    323 
    324   switch (type) {
    325     case SYN_STREAM:
    326       {
    327         SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false);
    328         header_data = syn_frame.header_block();
    329         header_length = syn_frame.header_block_len();
    330       }
    331       break;
    332     case SYN_REPLY:
    333       {
    334         SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false);
    335         header_data = syn_frame.header_block();
    336         header_length = syn_frame.header_block_len();
    337       }
    338       break;
    339     case HEADERS:
    340       {
    341         SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false);
    342         header_data = header_frame.header_block();
    343         header_length = header_frame.header_block_len();
    344       }
    345       break;
    346   }
    347 
    348   SpdyFrameBuilder builder(header_data, header_length);
    349   void* iter = NULL;
    350   uint16 num_headers;
    351   if (builder.ReadUInt16(&iter, &num_headers)) {
    352     int index;
    353     for (index = 0; index < num_headers; ++index) {
    354       std::string name;
    355       std::string value;
    356       if (!builder.ReadString(&iter, &name))
    357         break;
    358       if (!builder.ReadString(&iter, &value))
    359         break;
    360       if (!name.size() || !value.size())
    361         return false;
    362       if (block->find(name) == block->end()) {
    363         (*block)[name] = value;
    364       } else {
    365         return false;
    366       }
    367     }
    368     return index == num_headers &&
    369         iter == header_data + header_length;
    370   }
    371   return false;
    372 }
    373 
    374 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
    375                                             size_t max_bytes) {
    376   size_t bytes_to_read = std::min(*len, max_bytes);
    377   DCHECK_GE(current_frame_capacity_, current_frame_len_ + bytes_to_read);
    378   memcpy(&current_frame_buffer_[current_frame_len_], *data, bytes_to_read);
    379   current_frame_len_ += bytes_to_read;
    380   *data += bytes_to_read;
    381   *len -= bytes_to_read;
    382   return bytes_to_read;
    383 }
    384 
    385 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
    386                                                         size_t len) {
    387   DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
    388   DCHECK_GT(remaining_control_header_, 0u);
    389   size_t original_len = len;
    390 
    391   if (remaining_control_header_) {
    392     size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
    393                                                  remaining_control_header_);
    394     remaining_control_header_ -= bytes_read;
    395     if (remaining_control_header_ == 0) {
    396       SpdyControlFrame control_frame(current_frame_buffer_, false);
    397       DCHECK(control_frame.type() == SYN_STREAM ||
    398              control_frame.type() == SYN_REPLY ||
    399              control_frame.type() == HEADERS);
    400       visitor_->OnControl(&control_frame);
    401 
    402       CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
    403     }
    404   }
    405   return original_len - len;
    406 }
    407 
    408 // Does not buffer the control payload. Instead, either passes directly to the
    409 // visitor or decompresses and then passes directly to the visitor, via
    410 // IncrementallyDeliverControlFrameHeaderData() or
    411 // IncrementallyDecompressControlFrameHeaderData() respectively.
    412 size_t SpdyFramer::NewProcessControlFrameHeaderBlock(const char* data,
    413                                                      size_t data_len) {
    414   DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
    415   SpdyControlFrame control_frame(current_frame_buffer_, false);
    416   bool processed_successfully = true;
    417   DCHECK(control_frame.type() == SYN_STREAM ||
    418          control_frame.type() == SYN_REPLY ||
    419          control_frame.type() == HEADERS);
    420   size_t process_bytes = std::min(data_len, remaining_control_payload_);
    421   DCHECK_GT(process_bytes, 0u);
    422 
    423   if (enable_compression_) {
    424     processed_successfully = IncrementallyDecompressControlFrameHeaderData(
    425         &control_frame, data, process_bytes);
    426   } else {
    427     processed_successfully = IncrementallyDeliverControlFrameHeaderData(
    428         &control_frame, data, process_bytes);
    429   }
    430   remaining_control_payload_ -= process_bytes;
    431 
    432   // Handle the case that there is no futher data in this frame.
    433   if (remaining_control_payload_ == 0 && processed_successfully) {
    434     // The complete header block has been delivered. We send a zero-length
    435     // OnControlFrameHeaderData() to indicate this.
    436     visitor_->OnControlFrameHeaderData(
    437         GetControlFrameStreamId(&control_frame), NULL, 0);
    438 
    439     // If this is a FIN, tell the caller.
    440     if (control_frame.flags() & CONTROL_FLAG_FIN) {
    441       visitor_->OnStreamFrameData(GetControlFrameStreamId(&control_frame),
    442                                   NULL, 0);
    443     }
    444 
    445     CHANGE_STATE(SPDY_RESET);
    446   }
    447 
    448   // Handle error.
    449   if (!processed_successfully) {
    450     return data_len;
    451   }
    452 
    453   // Return amount processed.
    454   return process_bytes;
    455 }
    456 
    457 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
    458                                                   size_t data_len) {
    459   DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
    460   size_t original_data_len = data_len;
    461   SpdyControlFrame control_frame(current_frame_buffer_, false);
    462   bool read_successfully = true;
    463   DCHECK(control_frame.type() == SYN_STREAM ||
    464          control_frame.type() == SYN_REPLY ||
    465          control_frame.type() == HEADERS);
    466 
    467   if (enable_compression_) {
    468     // Note that the header block is held in the frame's payload, and is not
    469     // part of the frame's headers.
    470     if (remaining_control_payload_ > 0) {
    471       size_t bytes_read = UpdateCurrentFrameBuffer(
    472           &data,
    473           &data_len,
    474           remaining_control_payload_);
    475       remaining_control_payload_ -= bytes_read;
    476       if (remaining_control_payload_ == 0) {
    477         read_successfully = IncrementallyDecompressControlFrameHeaderData(
    478             &control_frame);
    479       }
    480     }
    481   } else {
    482     size_t bytes_to_send = std::min(data_len, remaining_control_payload_);
    483     DCHECK_GT(bytes_to_send, 0u);
    484     read_successfully = IncrementallyDeliverControlFrameHeaderData(
    485         &control_frame, data, bytes_to_send);
    486     data_len -= bytes_to_send;
    487     remaining_control_payload_ -= bytes_to_send;
    488   }
    489   if (remaining_control_payload_ == 0 && read_successfully) {
    490     // The complete header block has been delivered.
    491     visitor_->OnControlFrameHeaderData(GetControlFrameStreamId(&control_frame),
    492                                        NULL, 0);
    493 
    494     // If this is a FIN, tell the caller.
    495     if (control_frame.flags() & CONTROL_FLAG_FIN) {
    496       visitor_->OnStreamFrameData(GetControlFrameStreamId(&control_frame),
    497                                   NULL, 0);
    498     }
    499 
    500     CHANGE_STATE(SPDY_RESET);
    501   }
    502   if (!read_successfully) {
    503     return original_data_len;
    504   }
    505   return original_data_len - data_len;
    506 }
    507 
    508 /* static */
    509 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
    510                                           size_t header_length,
    511                                           SpdyHeaderBlock* block) {
    512   SpdyFrameBuilder builder(header_data, header_length);
    513   void* iter = NULL;
    514   uint16 num_headers;
    515   if (builder.ReadUInt16(&iter, &num_headers)) {
    516     for (int index = 0; index < num_headers; ++index) {
    517       std::string name;
    518       std::string value;
    519       if (!builder.ReadString(&iter, &name))
    520         return false;
    521       if (!builder.ReadString(&iter, &value))
    522         return false;
    523       if (block->find(name) == block->end()) {
    524         (*block)[name] = value;
    525       } else {
    526         return false;
    527       }
    528     }
    529     return true;
    530   }
    531   return false;
    532 }
    533 
    534 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream(
    535     SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority,
    536     SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) {
    537   SpdyFrameBuilder frame;
    538 
    539   DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0));
    540   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
    541   DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask);
    542 
    543   frame.WriteUInt16(kControlFlagMask | spdy_version_);
    544   frame.WriteUInt16(SYN_STREAM);
    545   frame.WriteUInt32(0);  // Placeholder for the length and flags
    546   frame.WriteUInt32(stream_id);
    547   frame.WriteUInt32(associated_stream_id);
    548   frame.WriteUInt16(ntohs(priority) << 6);  // Priority.
    549 
    550   frame.WriteUInt16(headers->size());  // Number of headers.
    551   SpdyHeaderBlock::const_iterator it;
    552   for (it = headers->begin(); it != headers->end(); ++it) {
    553     bool wrote_header;
    554     wrote_header = frame.WriteString(it->first);
    555     wrote_header &= frame.WriteString(it->second);
    556     DCHECK(wrote_header);
    557   }
    558 
    559   // Write the length and flags.
    560   size_t length = frame.length() - SpdyFrame::size();
    561   DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
    562   FlagsAndLength flags_length;
    563   flags_length.length_ = htonl(static_cast<uint32>(length));
    564   DCHECK_EQ(0, flags & ~kControlFlagsMask);
    565   flags_length.flags_[0] = flags;
    566   frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
    567 
    568   scoped_ptr<SpdySynStreamControlFrame> syn_frame(
    569       reinterpret_cast<SpdySynStreamControlFrame*>(frame.take()));
    570   if (compressed) {
    571     return reinterpret_cast<SpdySynStreamControlFrame*>(
    572         CompressControlFrame(*syn_frame.get()));
    573   }
    574   return syn_frame.release();
    575 }
    576 
    577 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id,
    578     SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) {
    579   DCHECK_GT(stream_id, 0u);
    580   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
    581 
    582   SpdyFrameBuilder frame;
    583 
    584   frame.WriteUInt16(kControlFlagMask | spdy_version_);
    585   frame.WriteUInt16(SYN_REPLY);
    586   frame.WriteUInt32(0);  // Placeholder for the length and flags.
    587   frame.WriteUInt32(stream_id);
    588   frame.WriteUInt16(0);  // Unused
    589 
    590   frame.WriteUInt16(headers->size());  // Number of headers.
    591   SpdyHeaderBlock::const_iterator it;
    592   for (it = headers->begin(); it != headers->end(); ++it) {
    593     bool wrote_header;
    594     wrote_header = frame.WriteString(it->first);
    595     wrote_header &= frame.WriteString(it->second);
    596     DCHECK(wrote_header);
    597   }
    598 
    599   // Write the length and flags.
    600   size_t length = frame.length() - SpdyFrame::size();
    601   DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
    602   FlagsAndLength flags_length;
    603   flags_length.length_ = htonl(static_cast<uint32>(length));
    604   DCHECK_EQ(0, flags & ~kControlFlagsMask);
    605   flags_length.flags_[0] = flags;
    606   frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
    607 
    608   scoped_ptr<SpdySynReplyControlFrame> reply_frame(
    609       reinterpret_cast<SpdySynReplyControlFrame*>(frame.take()));
    610   if (compressed) {
    611     return reinterpret_cast<SpdySynReplyControlFrame*>(
    612         CompressControlFrame(*reply_frame.get()));
    613   }
    614   return reply_frame.release();
    615 }
    616 
    617 /* static */
    618 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id,
    619                                                        SpdyStatusCodes status) {
    620   DCHECK_GT(stream_id, 0u);
    621   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
    622   DCHECK_NE(status, INVALID);
    623   DCHECK_LT(status, NUM_STATUS_CODES);
    624 
    625   SpdyFrameBuilder frame;
    626   frame.WriteUInt16(kControlFlagMask | spdy_version_);
    627   frame.WriteUInt16(RST_STREAM);
    628   frame.WriteUInt32(8);
    629   frame.WriteUInt32(stream_id);
    630   frame.WriteUInt32(status);
    631   return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take());
    632 }
    633 
    634 /* static */
    635 SpdySettingsControlFrame* SpdyFramer::CreateSettings(
    636     const SpdySettings& values) {
    637   SpdyFrameBuilder frame;
    638   frame.WriteUInt16(kControlFlagMask | spdy_version_);
    639   frame.WriteUInt16(SETTINGS);
    640   size_t settings_size = SpdySettingsControlFrame::size() - SpdyFrame::size() +
    641       8 * values.size();
    642   frame.WriteUInt32(settings_size);
    643   frame.WriteUInt32(values.size());
    644   SpdySettings::const_iterator it = values.begin();
    645   while (it != values.end()) {
    646     frame.WriteUInt32(it->first.id_);
    647     frame.WriteUInt32(it->second);
    648     ++it;
    649   }
    650   return reinterpret_cast<SpdySettingsControlFrame*>(frame.take());
    651 }
    652 
    653 /* static */
    654 SpdyNoOpControlFrame* SpdyFramer::CreateNopFrame() {
    655   SpdyFrameBuilder frame;
    656   frame.WriteUInt16(kControlFlagMask | spdy_version_);
    657   frame.WriteUInt16(NOOP);
    658   frame.WriteUInt32(0);
    659   return reinterpret_cast<SpdyNoOpControlFrame*>(frame.take());
    660 }
    661 
    662 /* static */
    663 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) {
    664   SpdyFrameBuilder frame;
    665   frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion);
    666   frame.WriteUInt16(PING);
    667   size_t ping_size = SpdyPingControlFrame::size() - SpdyFrame::size();
    668   frame.WriteUInt32(ping_size);
    669   frame.WriteUInt32(unique_id);
    670   return reinterpret_cast<SpdyPingControlFrame*>(frame.take());
    671 }
    672 
    673 /* static */
    674 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway(
    675     SpdyStreamId last_accepted_stream_id) {
    676   DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask);
    677 
    678   SpdyFrameBuilder frame;
    679   frame.WriteUInt16(kControlFlagMask | spdy_version_);
    680   frame.WriteUInt16(GOAWAY);
    681   size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size();
    682   frame.WriteUInt32(go_away_size);
    683   frame.WriteUInt32(last_accepted_stream_id);
    684   return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take());
    685 }
    686 
    687 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id,
    688     SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) {
    689   // Basically the same as CreateSynReply().
    690   DCHECK_GT(stream_id, 0u);
    691   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
    692 
    693   SpdyFrameBuilder frame;
    694   frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion);
    695   frame.WriteUInt16(HEADERS);
    696   frame.WriteUInt32(0);  // Placeholder for the length and flags.
    697   frame.WriteUInt32(stream_id);
    698   frame.WriteUInt16(0);  // Unused
    699 
    700   frame.WriteUInt16(headers->size());  // Number of headers.
    701   SpdyHeaderBlock::const_iterator it;
    702   for (it = headers->begin(); it != headers->end(); ++it) {
    703     bool wrote_header;
    704     wrote_header = frame.WriteString(it->first);
    705     wrote_header &= frame.WriteString(it->second);
    706     DCHECK(wrote_header);
    707   }
    708 
    709   // Write the length and flags.
    710   size_t length = frame.length() - SpdyFrame::size();
    711   DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
    712   FlagsAndLength flags_length;
    713   flags_length.length_ = htonl(static_cast<uint32>(length));
    714   DCHECK_EQ(0, flags & ~kControlFlagsMask);
    715   flags_length.flags_[0] = flags;
    716   frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
    717 
    718   scoped_ptr<SpdyHeadersControlFrame> headers_frame(
    719       reinterpret_cast<SpdyHeadersControlFrame*>(frame.take()));
    720   if (compressed) {
    721     return reinterpret_cast<SpdyHeadersControlFrame*>(
    722         CompressControlFrame(*headers_frame.get()));
    723   }
    724   return headers_frame.release();
    725 }
    726 
    727 /* static */
    728 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate(
    729     SpdyStreamId stream_id,
    730     uint32 delta_window_size) {
    731   DCHECK_GT(stream_id, 0u);
    732   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
    733   DCHECK_GT(delta_window_size, 0u);
    734   DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize);
    735 
    736   SpdyFrameBuilder frame;
    737   frame.WriteUInt16(kControlFlagMask | spdy_version_);
    738   frame.WriteUInt16(WINDOW_UPDATE);
    739   size_t window_update_size = SpdyWindowUpdateControlFrame::size() -
    740       SpdyFrame::size();
    741   frame.WriteUInt32(window_update_size);
    742   frame.WriteUInt32(stream_id);
    743   frame.WriteUInt32(delta_window_size);
    744   return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take());
    745 }
    746 
    747 /* static */
    748 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
    749                                SpdySettings* settings) {
    750   DCHECK_EQ(frame->type(), SETTINGS);
    751   DCHECK(settings);
    752 
    753   SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len());
    754   void* iter = NULL;
    755   for (size_t index = 0; index < frame->num_entries(); ++index) {
    756     uint32 id;
    757     uint32 value;
    758     if (!parser.ReadUInt32(&iter, &id))
    759       return false;
    760     if (!parser.ReadUInt32(&iter, &value))
    761       return false;
    762     settings->insert(settings->end(), std::make_pair(id, value));
    763   }
    764   return true;
    765 }
    766 
    767 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
    768                                            const char* data,
    769                                            uint32 len, SpdyDataFlags flags) {
    770   SpdyFrameBuilder frame;
    771 
    772   DCHECK_GT(stream_id, 0u);
    773   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
    774   frame.WriteUInt32(stream_id);
    775 
    776   DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask));
    777   FlagsAndLength flags_length;
    778   flags_length.length_ = htonl(len);
    779   DCHECK_EQ(0, flags & ~kDataFlagsMask);
    780   flags_length.flags_[0] = flags;
    781   frame.WriteBytes(&flags_length, sizeof(flags_length));
    782 
    783   frame.WriteBytes(data, len);
    784   scoped_ptr<SpdyFrame> data_frame(frame.take());
    785   SpdyDataFrame* rv;
    786   if (flags & DATA_FLAG_COMPRESSED) {
    787     rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get()));
    788   } else {
    789     rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
    790   }
    791 
    792   if (flags & DATA_FLAG_FIN) {
    793     CleanupCompressorForStream(stream_id);
    794   }
    795 
    796   return rv;
    797 }
    798 
    799 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) {
    800   if (frame.is_control_frame()) {
    801     return CompressControlFrame(
    802         reinterpret_cast<const SpdyControlFrame&>(frame));
    803   }
    804   return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
    805 }
    806 
    807 SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) {
    808   if (frame.is_control_frame()) {
    809     return DecompressControlFrame(
    810         reinterpret_cast<const SpdyControlFrame&>(frame));
    811   }
    812   return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
    813 }
    814 
    815 SpdyFrame* SpdyFramer::DuplicateFrame(const SpdyFrame& frame) {
    816   int size = SpdyFrame::size() + frame.length();
    817   SpdyFrame* new_frame = new SpdyFrame(size);
    818   memcpy(new_frame->data(), frame.data(), size);
    819   return new_frame;
    820 }
    821 
    822 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const {
    823   // The important frames to compress are those which contain large
    824   // amounts of compressible data - namely the headers in the SYN_STREAM
    825   // and SYN_REPLY.
    826   // TODO(mbelshe): Reconcile this with the spec when the spec is
    827   // explicit about which frames compress and which do not.
    828   if (frame.is_control_frame()) {
    829     const SpdyControlFrame& control_frame =
    830         reinterpret_cast<const SpdyControlFrame&>(frame);
    831     return control_frame.type() == SYN_STREAM ||
    832            control_frame.type() == SYN_REPLY;
    833   }
    834 
    835   const SpdyDataFrame& data_frame =
    836       reinterpret_cast<const SpdyDataFrame&>(frame);
    837   return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0;
    838 }
    839 
    840 const char* SpdyFramer::StateToString(int state) {
    841   switch (state) {
    842     case SPDY_ERROR:
    843       return "ERROR";
    844     case SPDY_DONE:
    845       return "DONE";
    846     case SPDY_AUTO_RESET:
    847       return "AUTO_RESET";
    848     case SPDY_RESET:
    849       return "RESET";
    850     case SPDY_READING_COMMON_HEADER:
    851       return "READING_COMMON_HEADER";
    852     case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
    853       return "INTERPRET_CONTROL_FRAME_COMMON_HEADER";
    854     case SPDY_CONTROL_FRAME_PAYLOAD:
    855       return "CONTROL_FRAME_PAYLOAD";
    856     case SPDY_IGNORE_REMAINING_PAYLOAD:
    857       return "IGNORE_REMAINING_PAYLOAD";
    858     case SPDY_FORWARD_STREAM_FRAME:
    859       return "FORWARD_STREAM_FRAME";
    860     case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
    861       return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
    862     case SPDY_CONTROL_FRAME_HEADER_BLOCK:
    863       return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
    864   }
    865   return "UNKNOWN_STATE";
    866 }
    867 
    868 const char* SpdyFramer::ErrorCodeToString(int error_code) {
    869   switch (error_code) {
    870     case SPDY_NO_ERROR:
    871       return "NO_ERROR";
    872     case SPDY_INVALID_CONTROL_FRAME:
    873       return "INVALID_CONTROL_FRAME";
    874     case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
    875       return "CONTROL_PAYLOAD_TOO_LARGE";
    876     case SPDY_ZLIB_INIT_FAILURE:
    877       return "ZLIB_INIT_FAILURE";
    878     case SPDY_UNSUPPORTED_VERSION:
    879       return "UNSUPPORTED_VERSION";
    880     case SPDY_DECOMPRESS_FAILURE:
    881       return "DECOMPRESS_FAILURE";
    882     case SPDY_COMPRESS_FAILURE:
    883       return "COMPRESS_FAILURE";
    884   }
    885   return "UNKNOWN_ERROR";
    886 }
    887 
    888 void SpdyFramer::set_enable_compression(bool value) {
    889   enable_compression_ = value;
    890 }
    891 
    892 void SpdyFramer::set_enable_compression_default(bool value) {
    893   compression_default_ = value;
    894 }
    895 
    896 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
    897   // This should only be called when we're in the SPDY_READING_COMMON_HEADER
    898   // state.
    899   DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
    900 
    901   size_t original_len = len;
    902   SpdyFrame current_frame(current_frame_buffer_, false);
    903 
    904   do {
    905     if (current_frame_len_ < SpdyFrame::size()) {
    906       size_t bytes_desired = SpdyFrame::size() - current_frame_len_;
    907       UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
    908       // Check for an empty data frame.
    909       if (current_frame_len_ == SpdyFrame::size() &&
    910           !current_frame.is_control_frame() &&
    911           current_frame.length() == 0) {
    912         if (current_frame.flags() & CONTROL_FLAG_FIN) {
    913           SpdyDataFrame data_frame(current_frame_buffer_, false);
    914           visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
    915         }
    916         CHANGE_STATE(SPDY_AUTO_RESET);
    917       }
    918       break;
    919     }
    920     remaining_data_ = current_frame.length();
    921 
    922     // This is just a sanity check for help debugging early frame errors.
    923     if (remaining_data_ > 1000000u) {
    924       LOG(WARNING) <<
    925           "Unexpectedly large frame.  Spdy session is likely corrupt.";
    926     }
    927 
    928     // if we're here, then we have the common header all received.
    929     if (!current_frame.is_control_frame())
    930       CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
    931     else
    932       CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER);
    933   } while (false);
    934 
    935   return original_len - len;
    936 }
    937 
    938 void SpdyFramer::ProcessControlFrameHeader() {
    939   DCHECK_EQ(SPDY_NO_ERROR, error_code_);
    940   DCHECK_LE(SpdyFrame::size(), current_frame_len_);
    941   SpdyControlFrame current_control_frame(current_frame_buffer_, false);
    942 
    943   // We check version before we check validity: version can never be 'invalid',
    944   // it can only be unsupported.
    945   if (current_control_frame.version() != spdy_version_) {
    946     set_error(SPDY_UNSUPPORTED_VERSION);
    947     return;
    948   }
    949 
    950   // Next up, check to see if we have valid data.  This should be after version
    951   // checking (otherwise if the the type were out of bounds due to a version
    952   // upgrade we would misclassify the error) and before checking the type
    953   // (type can definitely be out of bounds)
    954   if (!current_control_frame.AppearsToBeAValidControlFrame()) {
    955     set_error(SPDY_INVALID_CONTROL_FRAME);
    956     return;
    957   }
    958 
    959   // Do some sanity checking on the control frame sizes.
    960   switch (current_control_frame.type()) {
    961     case SYN_STREAM:
    962       if (current_control_frame.length() <
    963           SpdySynStreamControlFrame::size() - SpdyControlFrame::size())
    964         set_error(SPDY_INVALID_CONTROL_FRAME);
    965       break;
    966     case SYN_REPLY:
    967       if (current_control_frame.length() <
    968           SpdySynReplyControlFrame::size() - SpdyControlFrame::size())
    969         set_error(SPDY_INVALID_CONTROL_FRAME);
    970       break;
    971     case RST_STREAM:
    972       if (current_control_frame.length() !=
    973           SpdyRstStreamControlFrame::size() - SpdyFrame::size())
    974         set_error(SPDY_INVALID_CONTROL_FRAME);
    975       break;
    976     case SETTINGS:
    977       if (current_control_frame.length() <
    978           SpdySettingsControlFrame::size() - SpdyControlFrame::size())
    979         set_error(SPDY_INVALID_CONTROL_FRAME);
    980       break;
    981     // TODO(hkhalil): Remove NOOP.
    982     case NOOP:
    983       // NOOP.  Swallow it.
    984       DLOG(INFO) << "Attempted frame size validation for NOOP. Resetting.";
    985       CHANGE_STATE(SPDY_AUTO_RESET);
    986       return;
    987     case GOAWAY:
    988       if (current_control_frame.length() !=
    989           SpdyGoAwayControlFrame::size() - SpdyFrame::size())
    990         set_error(SPDY_INVALID_CONTROL_FRAME);
    991       break;
    992     case HEADERS:
    993       if (current_control_frame.length() <
    994           SpdyHeadersControlFrame::size() - SpdyControlFrame::size())
    995         set_error(SPDY_INVALID_CONTROL_FRAME);
    996       break;
    997     case WINDOW_UPDATE:
    998       if (current_control_frame.length() !=
    999           SpdyWindowUpdateControlFrame::size() - SpdyControlFrame::size())
   1000         set_error(SPDY_INVALID_CONTROL_FRAME);
   1001       break;
   1002     case PING:
   1003       if (current_control_frame.length() !=
   1004           SpdyPingControlFrame::size() - SpdyControlFrame::size())
   1005         set_error(SPDY_INVALID_CONTROL_FRAME);
   1006       break;
   1007     default:
   1008       LOG(WARNING) << "Valid spdy control frame with unhandled type: "
   1009                    << current_control_frame.type();
   1010       DCHECK(false);
   1011       set_error(SPDY_INVALID_CONTROL_FRAME);
   1012       break;
   1013   }
   1014 
   1015   remaining_control_payload_ = current_control_frame.length();
   1016   if (remaining_control_payload_ > kControlFrameBufferMaxSize) {
   1017     set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
   1018     return;
   1019   }
   1020 
   1021   ExpandControlFrameBuffer(remaining_control_payload_);
   1022   CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
   1023 }
   1024 
   1025 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
   1026   size_t original_len = len;
   1027   do {
   1028     if (remaining_control_payload_) {
   1029       size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
   1030                                                    remaining_control_payload_);
   1031       remaining_control_payload_ -= bytes_read;
   1032       remaining_data_ -= bytes_read;
   1033       if (remaining_control_payload_)
   1034         break;
   1035     }
   1036     SpdyControlFrame control_frame(current_frame_buffer_, false);
   1037     visitor_->OnControl(&control_frame);
   1038 
   1039     // If this is a FIN, tell the caller.
   1040     if (control_frame.type() == SYN_REPLY &&
   1041         control_frame.flags() & CONTROL_FLAG_FIN) {
   1042       visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>(
   1043                                       &control_frame)->stream_id(),
   1044                                   NULL, 0);
   1045     }
   1046 
   1047     CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
   1048   } while (false);
   1049   return original_len - len;
   1050 }
   1051 
   1052 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
   1053   size_t original_len = len;
   1054 
   1055   SpdyDataFrame current_data_frame(current_frame_buffer_, false);
   1056   if (remaining_data_) {
   1057     size_t amount_to_forward = std::min(remaining_data_, len);
   1058     if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
   1059       if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) {
   1060         z_stream* decompressor =
   1061             GetStreamDecompressor(current_data_frame.stream_id());
   1062         if (!decompressor)
   1063           return 0;
   1064 
   1065         size_t decompressed_max_size = amount_to_forward * 100;
   1066         scoped_array<char> decompressed(new char[decompressed_max_size]);
   1067         decompressor->next_in = reinterpret_cast<Bytef*>(
   1068             const_cast<char*>(data));
   1069         decompressor->avail_in = amount_to_forward;
   1070         decompressor->next_out =
   1071             reinterpret_cast<Bytef*>(decompressed.get());
   1072         decompressor->avail_out = decompressed_max_size;
   1073 
   1074         int rv = inflate(decompressor, Z_SYNC_FLUSH);
   1075         if (rv != Z_OK) {
   1076           LOG(WARNING) << "inflate failure: " << rv;
   1077           set_error(SPDY_DECOMPRESS_FAILURE);
   1078           return 0;
   1079         }
   1080         size_t decompressed_size = decompressed_max_size -
   1081                                    decompressor->avail_out;
   1082 
   1083         // Only inform the visitor if there is data.
   1084         if (decompressed_size)
   1085           visitor_->OnStreamFrameData(current_data_frame.stream_id(),
   1086                                       decompressed.get(),
   1087                                       decompressed_size);
   1088         amount_to_forward -= decompressor->avail_in;
   1089       } else {
   1090         // The data frame was not compressed.
   1091         // Only inform the visitor if there is data.
   1092         if (amount_to_forward)
   1093           visitor_->OnStreamFrameData(current_data_frame.stream_id(),
   1094                                       data, amount_to_forward);
   1095       }
   1096     }
   1097     data += amount_to_forward;
   1098     len -= amount_to_forward;
   1099     remaining_data_ -= amount_to_forward;
   1100 
   1101     // If the FIN flag is set, and there is no more data in this data
   1102     // frame, inform the visitor of EOF via a 0-length data frame.
   1103     if (!remaining_data_ &&
   1104         current_data_frame.flags() & DATA_FLAG_FIN) {
   1105       visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0);
   1106       CleanupDecompressorForStream(current_data_frame.stream_id());
   1107     }
   1108   } else {
   1109     CHANGE_STATE(SPDY_AUTO_RESET);
   1110   }
   1111   return original_len - len;
   1112 }
   1113 
   1114 z_stream* SpdyFramer::GetHeaderCompressor() {
   1115   if (header_compressor_.get())
   1116     return header_compressor_.get();  // Already initialized.
   1117 
   1118   header_compressor_.reset(new z_stream);
   1119   memset(header_compressor_.get(), 0, sizeof(z_stream));
   1120 
   1121   int success = deflateInit2(header_compressor_.get(),
   1122                              kCompressorLevel,
   1123                              Z_DEFLATED,
   1124                              kCompressorWindowSizeInBits,
   1125                              kCompressorMemLevel,
   1126                              Z_DEFAULT_STRATEGY);
   1127   if (success == Z_OK)
   1128     success = deflateSetDictionary(header_compressor_.get(),
   1129                                    reinterpret_cast<const Bytef*>(kDictionary),
   1130                                    kDictionarySize);
   1131   if (success != Z_OK) {
   1132     LOG(WARNING) << "deflateSetDictionary failure: " << success;
   1133     header_compressor_.reset(NULL);
   1134     return NULL;
   1135   }
   1136   return header_compressor_.get();
   1137 }
   1138 
   1139 z_stream* SpdyFramer::GetHeaderDecompressor() {
   1140   if (header_decompressor_.get())
   1141     return header_decompressor_.get();  // Already initialized.
   1142 
   1143   header_decompressor_.reset(new z_stream);
   1144   memset(header_decompressor_.get(), 0, sizeof(z_stream));
   1145 
   1146   // Compute the id of our dictionary so that we know we're using the
   1147   // right one when asked for it.
   1148   if (dictionary_id == 0) {
   1149     dictionary_id = adler32(0L, Z_NULL, 0);
   1150     dictionary_id = adler32(dictionary_id,
   1151                             reinterpret_cast<const Bytef*>(kDictionary),
   1152                             kDictionarySize);
   1153   }
   1154 
   1155   int success = inflateInit(header_decompressor_.get());
   1156   if (success != Z_OK) {
   1157     LOG(WARNING) << "inflateInit failure: " << success;
   1158     header_decompressor_.reset(NULL);
   1159     return NULL;
   1160   }
   1161   return header_decompressor_.get();
   1162 }
   1163 
   1164 z_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) {
   1165   CompressorMap::iterator it = stream_compressors_.find(stream_id);
   1166   if (it != stream_compressors_.end())
   1167     return it->second;  // Already initialized.
   1168 
   1169   scoped_ptr<z_stream> compressor(new z_stream);
   1170   memset(compressor.get(), 0, sizeof(z_stream));
   1171 
   1172   int success = deflateInit2(compressor.get(),
   1173                              kCompressorLevel,
   1174                              Z_DEFLATED,
   1175                              kCompressorWindowSizeInBits,
   1176                              kCompressorMemLevel,
   1177                              Z_DEFAULT_STRATEGY);
   1178   if (success != Z_OK) {
   1179     LOG(WARNING) << "deflateInit failure: " << success;
   1180     return NULL;
   1181   }
   1182   return stream_compressors_[stream_id] = compressor.release();
   1183 }
   1184 
   1185 z_stream* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id) {
   1186   CompressorMap::iterator it = stream_decompressors_.find(stream_id);
   1187   if (it != stream_decompressors_.end())
   1188     return it->second;  // Already initialized.
   1189 
   1190   scoped_ptr<z_stream> decompressor(new z_stream);
   1191   memset(decompressor.get(), 0, sizeof(z_stream));
   1192 
   1193   int success = inflateInit(decompressor.get());
   1194   if (success != Z_OK) {
   1195     LOG(WARNING) << "inflateInit failure: " << success;
   1196     return NULL;
   1197   }
   1198   return stream_decompressors_[stream_id] = decompressor.release();
   1199 }
   1200 
   1201 SpdyControlFrame* SpdyFramer::CompressControlFrame(
   1202     const SpdyControlFrame& frame) {
   1203   z_stream* compressor = GetHeaderCompressor();
   1204   if (!compressor)
   1205     return NULL;
   1206   return reinterpret_cast<SpdyControlFrame*>(
   1207       CompressFrameWithZStream(frame, compressor));
   1208 }
   1209 
   1210 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
   1211   z_stream* compressor = GetStreamCompressor(frame.stream_id());
   1212   if (!compressor)
   1213     return NULL;
   1214   return reinterpret_cast<SpdyDataFrame*>(
   1215       CompressFrameWithZStream(frame, compressor));
   1216 }
   1217 
   1218 SpdyControlFrame* SpdyFramer::DecompressControlFrame(
   1219     const SpdyControlFrame& frame) {
   1220   z_stream* decompressor = GetHeaderDecompressor();
   1221   if (!decompressor)
   1222     return NULL;
   1223   return reinterpret_cast<SpdyControlFrame*>(
   1224       DecompressFrameWithZStream(frame, decompressor));
   1225 }
   1226 
   1227 // Incrementally decompress the control frame's header block, feeding the
   1228 // result to the visitor in chunks. Continue this until the visitor
   1229 // indicates that it cannot process any more data, or (more commonly) we
   1230 // run out of data to deliver.
   1231 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
   1232     const SpdyControlFrame* control_frame) {
   1233   z_stream* decomp = GetHeaderDecompressor();
   1234   int payload_length;
   1235   int header_length;
   1236   const char* payload;
   1237   bool read_successfully = true;
   1238   bool more = true;
   1239   char buffer[kHeaderDataChunkMaxSize];
   1240 
   1241   if (!GetFrameBoundaries(
   1242       *control_frame, &payload_length, &header_length, &payload)) {
   1243     DLOG(ERROR) << "Control frame of type "
   1244                 << SpdyFramer::ControlTypeToString(control_frame->type())
   1245                 <<" doesn't have headers";
   1246     return false;
   1247   }
   1248   decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
   1249   decomp->avail_in = payload_length;
   1250   const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame);
   1251   DCHECK_LT(0u, stream_id);
   1252   while (more && read_successfully) {
   1253     decomp->next_out = reinterpret_cast<Bytef*>(buffer);
   1254     decomp->avail_out = arraysize(buffer);
   1255     int rv = DecompressHeaderBlockInZStream(decomp);
   1256     if (rv != Z_OK) {
   1257       set_error(SPDY_DECOMPRESS_FAILURE);
   1258       DLOG(WARNING) << "inflate failure: " << rv;
   1259       more = read_successfully = false;
   1260     } else {
   1261       DCHECK_GT(arraysize(buffer), decomp->avail_out);
   1262       size_t len = arraysize(buffer) - decomp->avail_out;
   1263       read_successfully = visitor_->OnControlFrameHeaderData(stream_id, buffer,
   1264                                                              len);
   1265       if (!read_successfully) {
   1266         // Assume that the problem was the header block was too large for the
   1267         // visitor.
   1268         set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
   1269       }
   1270       more = decomp->avail_in > 0;
   1271     }
   1272   }
   1273   return read_successfully;
   1274 }
   1275 
   1276 // Incrementally decompress the control frame's header block, feeding the
   1277 // result to the visitor in chunks. Continue this until the visitor
   1278 // indicates that it cannot process any more data, or (more commonly) we
   1279 // run out of data to deliver.
   1280 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
   1281     const SpdyControlFrame* control_frame,
   1282     const char* data,
   1283     size_t len) {
   1284   // Get a decompressor or set error.
   1285   z_stream* decomp = GetHeaderDecompressor();
   1286   if (decomp == NULL) {
   1287     LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
   1288     set_error(SPDY_DECOMPRESS_FAILURE);
   1289     return false;
   1290   }
   1291 
   1292   bool processed_successfully = true;
   1293   char buffer[kHeaderDataChunkMaxSize];
   1294 
   1295   decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
   1296   decomp->avail_in = len;
   1297   const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame);
   1298   DCHECK_LT(0u, stream_id);
   1299   while (decomp->avail_in > 0 && processed_successfully) {
   1300     decomp->next_out = reinterpret_cast<Bytef*>(buffer);
   1301     decomp->avail_out = arraysize(buffer);
   1302     int rv = DecompressHeaderBlockInZStream(decomp);
   1303     if (rv != Z_OK) {
   1304       set_error(SPDY_DECOMPRESS_FAILURE);
   1305       DLOG(WARNING) << "inflate failure: " << rv;
   1306       processed_successfully = false;
   1307     } else {
   1308       size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
   1309       if (decompressed_len > 0) {
   1310         processed_successfully = visitor_->OnControlFrameHeaderData(
   1311             stream_id, buffer, decompressed_len);
   1312       }
   1313       if (!processed_successfully) {
   1314         // Assume that the problem was the header block was too large for the
   1315         // visitor.
   1316         set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
   1317       }
   1318     }
   1319   }
   1320   return processed_successfully;
   1321 }
   1322 
   1323 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
   1324     const SpdyControlFrame* control_frame, const char* data, size_t len) {
   1325   bool read_successfully = true;
   1326   const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame);
   1327   DCHECK_LT(0u, stream_id);
   1328   while (read_successfully && len > 0) {
   1329     size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
   1330     read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
   1331                                                            bytes_to_deliver);
   1332     data += bytes_to_deliver;
   1333     len -= bytes_to_deliver;
   1334     if (!read_successfully) {
   1335       // Assume that the problem was the header block was too large for the
   1336       // visitor.
   1337       set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
   1338     }
   1339   }
   1340   return read_successfully;
   1341 }
   1342 
   1343 size_t SpdyFramer::GetMinimumControlFrameSize(SpdyControlType type) {
   1344   switch (type) {
   1345     case SYN_STREAM:
   1346       return SpdySynStreamControlFrame::size();
   1347     case SYN_REPLY:
   1348       return SpdySynReplyControlFrame::size();
   1349     case RST_STREAM:
   1350       return SpdyRstStreamControlFrame::size();
   1351     case SETTINGS:
   1352       return SpdySettingsControlFrame::size();
   1353     case NOOP:
   1354       return SpdyNoOpControlFrame::size();
   1355     case PING:
   1356       return SpdyPingControlFrame::size();
   1357     case GOAWAY:
   1358       return SpdyGoAwayControlFrame::size();
   1359     case HEADERS:
   1360       return SpdyHeadersControlFrame::size();
   1361     case WINDOW_UPDATE:
   1362       return SpdyWindowUpdateControlFrame::size();
   1363     case NUM_CONTROL_FRAME_TYPES:
   1364       break;
   1365   }
   1366   LOG(ERROR) << "Unknown SPDY control frame type " << type;
   1367   return 0x7FFFFFFF;  // Max signed 32bit int
   1368 }
   1369 
   1370 /* static */
   1371 SpdyStreamId SpdyFramer::GetControlFrameStreamId(
   1372     const SpdyControlFrame* control_frame) {
   1373   SpdyStreamId stream_id = kInvalidStream;
   1374   if (control_frame != NULL) {
   1375     switch (control_frame->type()) {
   1376       case SYN_STREAM:
   1377         stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>(
   1378             control_frame)->stream_id();
   1379         break;
   1380       case SYN_REPLY:
   1381         stream_id = reinterpret_cast<const SpdySynReplyControlFrame*>(
   1382             control_frame)->stream_id();
   1383         break;
   1384       case HEADERS:
   1385         stream_id = reinterpret_cast<const SpdyHeadersControlFrame*>(
   1386             control_frame)->stream_id();
   1387         break;
   1388       case RST_STREAM:
   1389         stream_id = reinterpret_cast<const SpdyRstStreamControlFrame*>(
   1390             control_frame)->stream_id();
   1391         break;
   1392       case WINDOW_UPDATE:
   1393         stream_id = reinterpret_cast<const SpdyWindowUpdateControlFrame*>(
   1394             control_frame)->stream_id();
   1395         break;
   1396       // All of the following types are not part of a particular stream.
   1397       // They all fall through to the invalid control frame type case.
   1398       // (The default case isn't used so that the compile will break if a new
   1399       // control frame type is added but not included here.)
   1400       case SETTINGS:
   1401       case NOOP:
   1402       case PING:
   1403       case GOAWAY:
   1404       case NUM_CONTROL_FRAME_TYPES:  // makes compiler happy
   1405         break;
   1406     }
   1407   }
   1408   return stream_id;
   1409 }
   1410 
   1411 void SpdyFramer::set_validate_control_frame_sizes(bool value) {
   1412   validate_control_frame_sizes_ = value;
   1413 }
   1414 
   1415 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) {
   1416   z_stream* decompressor = GetStreamDecompressor(frame.stream_id());
   1417   if (!decompressor)
   1418     return NULL;
   1419   return reinterpret_cast<SpdyDataFrame*>(
   1420       DecompressFrameWithZStream(frame, decompressor));
   1421 }
   1422 
   1423 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame,
   1424                                                 z_stream* compressor) {
   1425   int payload_length;
   1426   int header_length;
   1427   const char* payload;
   1428 
   1429   base::StatsCounter compressed_frames("spdy.CompressedFrames");
   1430   base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
   1431   base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
   1432 
   1433   if (!enable_compression_)
   1434     return DuplicateFrame(frame);
   1435 
   1436   if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload))
   1437     return NULL;
   1438 
   1439   // Create an output frame.
   1440   int compressed_max_size = deflateBound(compressor, payload_length);
   1441   int new_frame_size = header_length + compressed_max_size;
   1442   scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size));
   1443   memcpy(new_frame->data(), frame.data(), frame.length() + SpdyFrame::size());
   1444 
   1445   compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
   1446   compressor->avail_in = payload_length;
   1447   compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
   1448                           header_length;
   1449   compressor->avail_out = compressed_max_size;
   1450 
   1451   // Data packets have a 'compressed' flag.
   1452   if (!new_frame->is_control_frame()) {
   1453     SpdyDataFrame* data_frame =
   1454         reinterpret_cast<SpdyDataFrame*>(new_frame.get());
   1455     data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED);
   1456   }
   1457 
   1458 #ifndef ANDROID
   1459   // Make sure that all the data we pass to zlib is defined.
   1460   // This way, all Valgrind reports on the compressed data are zlib's fault.
   1461   (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in,
   1462                                       compressor->avail_in);
   1463 #endif
   1464 
   1465   int rv = deflate(compressor, Z_SYNC_FLUSH);
   1466   if (rv != Z_OK) {  // How can we know that it compressed everything?
   1467     // This shouldn't happen, right?
   1468     LOG(WARNING) << "deflate failure: " << rv;
   1469     return NULL;
   1470   }
   1471 
   1472   int compressed_size = compressed_max_size - compressor->avail_out;
   1473 
   1474 #ifndef ANDROID
   1475   // We trust zlib. Also, we can't do anything about it.
   1476   // See http://www.zlib.net/zlib_faq.html#faq36
   1477   (void)VALGRIND_MAKE_MEM_DEFINED(new_frame->data() + header_length,
   1478                                   compressed_size);
   1479 #endif
   1480 
   1481   new_frame->set_length(header_length + compressed_size - SpdyFrame::size());
   1482 
   1483   pre_compress_bytes.Add(payload_length);
   1484   post_compress_bytes.Add(new_frame->length());
   1485 
   1486   compressed_frames.Increment();
   1487 
   1488   return new_frame.release();
   1489 }
   1490 
   1491 SpdyFrame* SpdyFramer::DecompressFrameWithZStream(const SpdyFrame& frame,
   1492                                                   z_stream* decompressor) {
   1493   int payload_length;
   1494   int header_length;
   1495   const char* payload;
   1496 
   1497   base::StatsCounter decompressed_frames("spdy.DecompressedFrames");
   1498   base::StatsCounter pre_decompress_bytes("spdy.PreDeCompressSize");
   1499   base::StatsCounter post_decompress_bytes("spdy.PostDeCompressSize");
   1500 
   1501   if (!enable_compression_)
   1502     return DuplicateFrame(frame);
   1503 
   1504   if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload))
   1505     return NULL;
   1506 
   1507   if (!frame.is_control_frame()) {
   1508     const SpdyDataFrame& data_frame =
   1509         reinterpret_cast<const SpdyDataFrame&>(frame);
   1510     if ((data_frame.flags() & DATA_FLAG_COMPRESSED) == 0)
   1511       return DuplicateFrame(frame);
   1512   }
   1513 
   1514   // Create an output frame.  Assume it does not need to be longer than
   1515   // the input data.
   1516   size_t decompressed_max_size = kControlFrameBufferInitialSize;
   1517   int new_frame_size = header_length + decompressed_max_size;
   1518   if (frame.length() > decompressed_max_size)
   1519     return NULL;
   1520   scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size));
   1521   memcpy(new_frame->data(), frame.data(), frame.length() + SpdyFrame::size());
   1522 
   1523   decompressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
   1524   decompressor->avail_in = payload_length;
   1525   decompressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
   1526       header_length;
   1527   decompressor->avail_out = decompressed_max_size;
   1528 
   1529   int rv = inflate(decompressor, Z_SYNC_FLUSH);
   1530   if (rv == Z_NEED_DICT) {
   1531     // Need to try again with the right dictionary.
   1532     if (decompressor->adler == dictionary_id) {
   1533       rv = inflateSetDictionary(decompressor, (const Bytef*)kDictionary,
   1534                                 kDictionarySize);
   1535       if (rv == Z_OK)
   1536         rv = inflate(decompressor, Z_SYNC_FLUSH);
   1537     }
   1538   }
   1539   if (rv != Z_OK) {  // How can we know that it decompressed everything?
   1540     LOG(WARNING) << "inflate failure: " << rv;
   1541     return NULL;
   1542   }
   1543 
   1544   // Unset the compressed flag for data frames.
   1545   if (!new_frame->is_control_frame()) {
   1546     SpdyDataFrame* data_frame =
   1547         reinterpret_cast<SpdyDataFrame*>(new_frame.get());
   1548     data_frame->set_flags(data_frame->flags() & ~DATA_FLAG_COMPRESSED);
   1549   }
   1550 
   1551   int decompressed_size = decompressed_max_size - decompressor->avail_out;
   1552   new_frame->set_length(header_length + decompressed_size - SpdyFrame::size());
   1553 
   1554   // If there is data left, then the frame didn't fully decompress.  This
   1555   // means that there is stranded data at the end of this frame buffer which
   1556   // will be ignored.
   1557   DCHECK_EQ(decompressor->avail_in, 0u);
   1558 
   1559   pre_decompress_bytes.Add(frame.length());
   1560   post_decompress_bytes.Add(new_frame->length());
   1561 
   1562   decompressed_frames.Increment();
   1563 
   1564   return new_frame.release();
   1565 }
   1566 
   1567 void SpdyFramer::CleanupCompressorForStream(SpdyStreamId id) {
   1568   CompressorMap::iterator it = stream_compressors_.find(id);
   1569   if (it != stream_compressors_.end()) {
   1570     z_stream* compressor = it->second;
   1571     deflateEnd(compressor);
   1572     delete compressor;
   1573     stream_compressors_.erase(it);
   1574   }
   1575 }
   1576 
   1577 void SpdyFramer::CleanupDecompressorForStream(SpdyStreamId id) {
   1578   CompressorMap::iterator it = stream_decompressors_.find(id);
   1579   if (it != stream_decompressors_.end()) {
   1580     z_stream* decompressor = it->second;
   1581     inflateEnd(decompressor);
   1582     delete decompressor;
   1583     stream_decompressors_.erase(it);
   1584   }
   1585 }
   1586 
   1587 void SpdyFramer::CleanupStreamCompressorsAndDecompressors() {
   1588   CompressorMap::iterator it;
   1589 
   1590   it = stream_compressors_.begin();
   1591   while (it != stream_compressors_.end()) {
   1592     z_stream* compressor = it->second;
   1593     deflateEnd(compressor);
   1594     delete compressor;
   1595     ++it;
   1596   }
   1597   stream_compressors_.clear();
   1598 
   1599   it = stream_decompressors_.begin();
   1600   while (it != stream_decompressors_.end()) {
   1601     z_stream* decompressor = it->second;
   1602     inflateEnd(decompressor);
   1603     delete decompressor;
   1604     ++it;
   1605   }
   1606   stream_decompressors_.clear();
   1607 }
   1608 
   1609 size_t SpdyFramer::BytesSafeToRead() const {
   1610   switch (state_) {
   1611     case SPDY_ERROR:
   1612     case SPDY_DONE:
   1613     case SPDY_AUTO_RESET:
   1614     case SPDY_RESET:
   1615       return 0;
   1616     case SPDY_READING_COMMON_HEADER:
   1617       DCHECK_LT(current_frame_len_, SpdyFrame::size());
   1618       return SpdyFrame::size() - current_frame_len_;
   1619     case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
   1620       return 0;
   1621     // TODO(rtenneti): Add support for SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
   1622     // and SPDY_CONTROL_FRAME_HEADER_BLOCK.
   1623     case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
   1624     case SPDY_CONTROL_FRAME_HEADER_BLOCK:
   1625       return 0;
   1626     case SPDY_CONTROL_FRAME_PAYLOAD:
   1627     case SPDY_IGNORE_REMAINING_PAYLOAD:
   1628     case SPDY_FORWARD_STREAM_FRAME:
   1629       return remaining_data_;
   1630   }
   1631   // We should never get to here.
   1632   return 0;
   1633 }
   1634 
   1635 void SpdyFramer::set_error(SpdyError error) {
   1636   DCHECK(visitor_);
   1637   error_code_ = error;
   1638   CHANGE_STATE(SPDY_ERROR);
   1639   visitor_->OnError(this);
   1640 }
   1641 
   1642 void SpdyFramer::ExpandControlFrameBuffer(size_t size) {
   1643   size_t alloc_size = size + SpdyFrame::size();
   1644   DCHECK_LE(alloc_size, kControlFrameBufferMaxSize);
   1645   if (alloc_size <= current_frame_capacity_)
   1646     return;
   1647   char* new_buffer = new char[alloc_size];
   1648   memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
   1649   delete [] current_frame_buffer_;
   1650   current_frame_capacity_ = alloc_size;
   1651   current_frame_buffer_ = new_buffer;
   1652 }
   1653 
   1654 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame,
   1655                                     int* payload_length,
   1656                                     int* header_length,
   1657                                     const char** payload) const {
   1658   size_t frame_size;
   1659   if (frame.is_control_frame()) {
   1660     const SpdyControlFrame& control_frame =
   1661         reinterpret_cast<const SpdyControlFrame&>(frame);
   1662     switch (control_frame.type()) {
   1663       case SYN_STREAM:
   1664         {
   1665           const SpdySynStreamControlFrame& syn_frame =
   1666               reinterpret_cast<const SpdySynStreamControlFrame&>(frame);
   1667           frame_size = SpdySynStreamControlFrame::size();
   1668           *payload_length = syn_frame.header_block_len();
   1669           *header_length = frame_size;
   1670           *payload = frame.data() + *header_length;
   1671         }
   1672         break;
   1673       case SYN_REPLY:
   1674         {
   1675           const SpdySynReplyControlFrame& syn_frame =
   1676               reinterpret_cast<const SpdySynReplyControlFrame&>(frame);
   1677           frame_size = SpdySynReplyControlFrame::size();
   1678           *payload_length = syn_frame.header_block_len();
   1679           *header_length = frame_size;
   1680           *payload = frame.data() + *header_length;
   1681         }
   1682         break;
   1683       case HEADERS:
   1684         {
   1685           const SpdyHeadersControlFrame& headers_frame =
   1686               reinterpret_cast<const SpdyHeadersControlFrame&>(frame);
   1687           frame_size = SpdyHeadersControlFrame::size();
   1688           *payload_length = headers_frame.header_block_len();
   1689           *header_length = frame_size;
   1690           *payload = frame.data() + *header_length;
   1691         }
   1692         break;
   1693       default:
   1694         // TODO(mbelshe): set an error?
   1695         return false;  // We can't compress this frame!
   1696     }
   1697   } else {
   1698     frame_size = SpdyFrame::size();
   1699     *header_length = frame_size;
   1700     *payload_length = frame.length();
   1701     *payload = frame.data() + SpdyFrame::size();
   1702   }
   1703   return true;
   1704 }
   1705 
   1706 }  // namespace spdy
   1707