• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 uLong dictionary_id = 0;
35 
36 }  // namespace
37 
38 namespace spdy {
39 
40 // This is just a hacked dictionary to use for shrinking HTTP-like headers.
41 // TODO(mbelshe): Use a scientific methodology for computing the dictionary.
42 const char SpdyFramer::kDictionary[] =
43   "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
44   "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
45   "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
46   "-agent10010120020120220320420520630030130230330430530630740040140240340440"
47   "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
48   "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
49   "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
50   "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
51   "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
52   "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
53   "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
54   "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
55   ".1statusversionurl";
56 const int SpdyFramer::kDictionarySize = arraysize(kDictionary);
57 
58 // By default is compression on or off.
59 bool SpdyFramer::compression_default_ = true;
60 int SpdyFramer::spdy_version_ = kSpdyProtocolVersion;
61 
62 // The initial size of the control frame buffer; this is used internally
63 // as we parse through control frames. (It is exposed here for unit test
64 // purposes.)
65 size_t SpdyFramer::kControlFrameBufferInitialSize = 8 * 1024;
66 
67 // The maximum size of the control frame buffer that we support.
68 // TODO(mbelshe): We should make this stream-based so there are no limits.
69 size_t SpdyFramer::kControlFrameBufferMaxSize = 16 * 1024;
70 
71 #ifdef DEBUG_SPDY_STATE_CHANGES
72 #define CHANGE_STATE(newstate) \
73 { \
74   do { \
75     LOG(INFO) << "Changing state from: " \
76       << StateToString(state_) \
77       << " to " << StateToString(newstate) << "\n"; \
78     state_ = newstate; \
79   } while (false); \
80 }
81 #else
82 #define CHANGE_STATE(newstate) (state_ = newstate)
83 #endif
84 
SpdyFramer()85 SpdyFramer::SpdyFramer()
86     : state_(SPDY_RESET),
87       error_code_(SPDY_NO_ERROR),
88       remaining_payload_(0),
89       remaining_control_payload_(0),
90       current_frame_buffer_(NULL),
91       current_frame_len_(0),
92       current_frame_capacity_(0),
93       enable_compression_(compression_default_),
94       visitor_(NULL) {
95 }
96 
~SpdyFramer()97 SpdyFramer::~SpdyFramer() {
98   if (header_compressor_.get()) {
99     deflateEnd(header_compressor_.get());
100   }
101   if (header_decompressor_.get()) {
102     inflateEnd(header_decompressor_.get());
103   }
104   CleanupStreamCompressorsAndDecompressors();
105   delete [] current_frame_buffer_;
106 }
107 
ProcessInput(const char * data,size_t len)108 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
109   DCHECK(visitor_);
110   DCHECK(data);
111 
112   size_t original_len = len;
113   while (len != 0) {
114     switch (state_) {
115       case SPDY_ERROR:
116       case SPDY_DONE:
117         goto bottom;
118 
119       case SPDY_AUTO_RESET:
120       case SPDY_RESET:
121         Reset();
122         CHANGE_STATE(SPDY_READING_COMMON_HEADER);
123         continue;
124 
125       case SPDY_READING_COMMON_HEADER: {
126         size_t bytes_read = ProcessCommonHeader(data, len);
127         len -= bytes_read;
128         data += bytes_read;
129         continue;
130       }
131 
132       // Arguably, this case is not necessary, as no bytes are consumed here.
133       // I felt it was a nice partitioning, however (which probably indicates
134       // that it should be refactored into its own function!)
135       case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
136         ProcessControlFrameHeader();
137         continue;
138 
139       case SPDY_CONTROL_FRAME_PAYLOAD: {
140         size_t bytes_read = ProcessControlFramePayload(data, len);
141         len -= bytes_read;
142         data += bytes_read;
143       }
144         // intentional fallthrough
145       case SPDY_IGNORE_REMAINING_PAYLOAD:
146         // control frame has too-large payload
147         // intentional fallthrough
148       case SPDY_FORWARD_STREAM_FRAME: {
149         size_t bytes_read = ProcessDataFramePayload(data, len);
150         len -= bytes_read;
151         data += bytes_read;
152         continue;
153       }
154       default:
155         break;
156     }
157   }
158  bottom:
159   return original_len - len;
160 }
161 
Reset()162 void SpdyFramer::Reset() {
163   state_ = SPDY_RESET;
164   error_code_ = SPDY_NO_ERROR;
165   remaining_payload_ = 0;
166   remaining_control_payload_ = 0;
167   current_frame_len_ = 0;
168   if (current_frame_capacity_ != kControlFrameBufferInitialSize) {
169     delete [] current_frame_buffer_;
170     current_frame_buffer_ = 0;
171     current_frame_capacity_ = 0;
172     ExpandControlFrameBuffer(kControlFrameBufferInitialSize);
173   }
174 }
175 
ParseHeaderBlock(const SpdyFrame * frame,SpdyHeaderBlock * block)176 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame,
177                                   SpdyHeaderBlock* block) {
178   SpdyControlFrame control_frame(frame->data(), false);
179   uint32 type = control_frame.type();
180   if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS)
181     return false;
182 
183   // Find the header data within the control frame.
184   scoped_ptr<SpdyFrame> decompressed_frame(DecompressFrame(*frame));
185   if (!decompressed_frame.get())
186     return false;
187 
188   const char *header_data = NULL;
189   int header_length = 0;
190 
191   switch (type) {
192     case SYN_STREAM:
193       {
194         SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false);
195         header_data = syn_frame.header_block();
196         header_length = syn_frame.header_block_len();
197       }
198       break;
199     case SYN_REPLY:
200       {
201         SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false);
202         header_data = syn_frame.header_block();
203         header_length = syn_frame.header_block_len();
204       }
205       break;
206     case HEADERS:
207       {
208         SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false);
209         header_data = header_frame.header_block();
210         header_length = header_frame.header_block_len();
211       }
212       break;
213   }
214 
215   SpdyFrameBuilder builder(header_data, header_length);
216   void* iter = NULL;
217   uint16 num_headers;
218   if (builder.ReadUInt16(&iter, &num_headers)) {
219     int index;
220     for (index = 0; index < num_headers; ++index) {
221       std::string name;
222       std::string value;
223       if (!builder.ReadString(&iter, &name))
224         break;
225       if (!builder.ReadString(&iter, &value))
226         break;
227       if (!name.size() || !value.size())
228         return false;
229       if (block->find(name) == block->end()) {
230         (*block)[name] = value;
231       } else {
232         return false;
233       }
234     }
235     return index == num_headers &&
236         iter == header_data + header_length;
237   }
238   return false;
239 }
240 
CreateSynStream(SpdyStreamId stream_id,SpdyStreamId associated_stream_id,int priority,SpdyControlFlags flags,bool compressed,SpdyHeaderBlock * headers)241 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream(
242     SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority,
243     SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
244   SpdyFrameBuilder frame;
245 
246   DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0));
247   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
248   DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask);
249 
250   frame.WriteUInt16(kControlFlagMask | spdy_version_);
251   frame.WriteUInt16(SYN_STREAM);
252   frame.WriteUInt32(0);  // Placeholder for the length and flags
253   frame.WriteUInt32(stream_id);
254   frame.WriteUInt32(associated_stream_id);
255   frame.WriteUInt16(ntohs(priority) << 6);  // Priority.
256 
257   frame.WriteUInt16(headers->size());  // Number of headers.
258   SpdyHeaderBlock::iterator it;
259   for (it = headers->begin(); it != headers->end(); ++it) {
260     bool wrote_header;
261     wrote_header = frame.WriteString(it->first);
262     wrote_header &= frame.WriteString(it->second);
263     DCHECK(wrote_header);
264   }
265 
266   // Write the length and flags.
267   size_t length = frame.length() - SpdyFrame::size();
268   DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
269   FlagsAndLength flags_length;
270   flags_length.length_ = htonl(static_cast<uint32>(length));
271   DCHECK_EQ(0, flags & ~kControlFlagsMask);
272   flags_length.flags_[0] = flags;
273   frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
274 
275   scoped_ptr<SpdyFrame> syn_frame(frame.take());
276   if (compressed) {
277     return reinterpret_cast<SpdySynStreamControlFrame*>(
278         CompressFrame(*syn_frame.get()));
279   }
280   return reinterpret_cast<SpdySynStreamControlFrame*>(syn_frame.release());
281 }
282 
CreateSynReply(SpdyStreamId stream_id,SpdyControlFlags flags,bool compressed,SpdyHeaderBlock * headers)283 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id,
284     SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
285   DCHECK_GT(stream_id, 0u);
286   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
287 
288   SpdyFrameBuilder frame;
289 
290   frame.WriteUInt16(kControlFlagMask | spdy_version_);
291   frame.WriteUInt16(SYN_REPLY);
292   frame.WriteUInt32(0);  // Placeholder for the length and flags.
293   frame.WriteUInt32(stream_id);
294   frame.WriteUInt16(0);  // Unused
295 
296   frame.WriteUInt16(headers->size());  // Number of headers.
297   SpdyHeaderBlock::iterator it;
298   for (it = headers->begin(); it != headers->end(); ++it) {
299     bool wrote_header;
300     wrote_header = frame.WriteString(it->first);
301     wrote_header &= frame.WriteString(it->second);
302     DCHECK(wrote_header);
303   }
304 
305   // Write the length and flags.
306   size_t length = frame.length() - SpdyFrame::size();
307   DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
308   FlagsAndLength flags_length;
309   flags_length.length_ = htonl(static_cast<uint32>(length));
310   DCHECK_EQ(0, flags & ~kControlFlagsMask);
311   flags_length.flags_[0] = flags;
312   frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
313 
314   scoped_ptr<SpdyFrame> reply_frame(frame.take());
315   if (compressed) {
316     return reinterpret_cast<SpdySynReplyControlFrame*>(
317         CompressFrame(*reply_frame.get()));
318   }
319   return reinterpret_cast<SpdySynReplyControlFrame*>(reply_frame.release());
320 }
321 
322 /* static */
CreateRstStream(SpdyStreamId stream_id,SpdyStatusCodes status)323 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id,
324                                                        SpdyStatusCodes status) {
325   DCHECK_GT(stream_id, 0u);
326   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
327   DCHECK_NE(status, INVALID);
328   DCHECK_LT(status, NUM_STATUS_CODES);
329 
330   SpdyFrameBuilder frame;
331   frame.WriteUInt16(kControlFlagMask | spdy_version_);
332   frame.WriteUInt16(RST_STREAM);
333   frame.WriteUInt32(8);
334   frame.WriteUInt32(stream_id);
335   frame.WriteUInt32(status);
336   return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take());
337 }
338 
339 /* static */
CreateSettings(const SpdySettings & values)340 SpdySettingsControlFrame* SpdyFramer::CreateSettings(
341     const SpdySettings& values) {
342   SpdyFrameBuilder frame;
343   frame.WriteUInt16(kControlFlagMask | spdy_version_);
344   frame.WriteUInt16(SETTINGS);
345   size_t settings_size = SpdySettingsControlFrame::size() - SpdyFrame::size() +
346       8 * values.size();
347   frame.WriteUInt32(settings_size);
348   frame.WriteUInt32(values.size());
349   SpdySettings::const_iterator it = values.begin();
350   while (it != values.end()) {
351     frame.WriteUInt32(it->first.id_);
352     frame.WriteUInt32(it->second);
353     ++it;
354   }
355   return reinterpret_cast<SpdySettingsControlFrame*>(frame.take());
356 }
357 
358 /* static */
CreateNopFrame()359 SpdyControlFrame* SpdyFramer::CreateNopFrame() {
360   SpdyFrameBuilder frame;
361   frame.WriteUInt16(kControlFlagMask | spdy_version_);
362   frame.WriteUInt16(NOOP);
363   frame.WriteUInt32(0);
364   return reinterpret_cast<SpdyControlFrame*>(frame.take());
365 }
366 
367 /* static */
CreateGoAway(SpdyStreamId last_accepted_stream_id)368 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway(
369     SpdyStreamId last_accepted_stream_id) {
370   DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask);
371 
372   SpdyFrameBuilder frame;
373   frame.WriteUInt16(kControlFlagMask | spdy_version_);
374   frame.WriteUInt16(GOAWAY);
375   size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size();
376   frame.WriteUInt32(go_away_size);
377   frame.WriteUInt32(last_accepted_stream_id);
378   return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take());
379 }
380 
CreateHeaders(SpdyStreamId stream_id,SpdyControlFlags flags,bool compressed,SpdyHeaderBlock * headers)381 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id,
382     SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
383   // Basically the same as CreateSynReply().
384   DCHECK_GT(stream_id, 0u);
385   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
386 
387   SpdyFrameBuilder frame;
388   frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion);
389   frame.WriteUInt16(HEADERS);
390   frame.WriteUInt32(0);  // Placeholder for the length and flags.
391   frame.WriteUInt32(stream_id);
392   frame.WriteUInt16(0);  // Unused
393 
394   frame.WriteUInt16(headers->size());  // Number of headers.
395   SpdyHeaderBlock::iterator it;
396   for (it = headers->begin(); it != headers->end(); ++it) {
397     bool wrote_header;
398     wrote_header = frame.WriteString(it->first);
399     wrote_header &= frame.WriteString(it->second);
400     DCHECK(wrote_header);
401   }
402 
403   // Write the length and flags.
404   size_t length = frame.length() - SpdyFrame::size();
405   DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
406   FlagsAndLength flags_length;
407   flags_length.length_ = htonl(static_cast<uint32>(length));
408   DCHECK_EQ(0, flags & ~kControlFlagsMask);
409   flags_length.flags_[0] = flags;
410   frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length));
411 
412   scoped_ptr<SpdyFrame> headers_frame(frame.take());
413   if (compressed) {
414     return reinterpret_cast<SpdyHeadersControlFrame*>(
415         CompressFrame(*headers_frame.get()));
416   }
417   return reinterpret_cast<SpdyHeadersControlFrame*>(headers_frame.release());
418 }
419 
420 /* static */
CreateWindowUpdate(SpdyStreamId stream_id,uint32 delta_window_size)421 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate(
422     SpdyStreamId stream_id,
423     uint32 delta_window_size) {
424   DCHECK_GT(stream_id, 0u);
425   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
426   DCHECK_GT(delta_window_size, 0u);
427   DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize);
428 
429   SpdyFrameBuilder frame;
430   frame.WriteUInt16(kControlFlagMask | spdy_version_);
431   frame.WriteUInt16(WINDOW_UPDATE);
432   size_t window_update_size = SpdyWindowUpdateControlFrame::size() -
433       SpdyFrame::size();
434   frame.WriteUInt32(window_update_size);
435   frame.WriteUInt32(stream_id);
436   frame.WriteUInt32(delta_window_size);
437   return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take());
438 }
439 
440 /* static */
ParseSettings(const SpdySettingsControlFrame * frame,SpdySettings * settings)441 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
442                                SpdySettings* settings) {
443   DCHECK_EQ(frame->type(), SETTINGS);
444   DCHECK(settings);
445 
446   SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len());
447   void* iter = NULL;
448   for (size_t index = 0; index < frame->num_entries(); ++index) {
449     uint32 id;
450     uint32 value;
451     if (!parser.ReadUInt32(&iter, &id))
452       return false;
453     if (!parser.ReadUInt32(&iter, &value))
454       return false;
455     settings->insert(settings->end(), std::make_pair(id, value));
456   }
457   return true;
458 }
459 
CreateDataFrame(SpdyStreamId stream_id,const char * data,uint32 len,SpdyDataFlags flags)460 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
461                                            const char* data,
462                                            uint32 len, SpdyDataFlags flags) {
463   SpdyFrameBuilder frame;
464 
465   DCHECK_GT(stream_id, 0u);
466   DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
467   frame.WriteUInt32(stream_id);
468 
469   DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask));
470   FlagsAndLength flags_length;
471   flags_length.length_ = htonl(len);
472   DCHECK_EQ(0, flags & ~kDataFlagsMask);
473   flags_length.flags_[0] = flags;
474   frame.WriteBytes(&flags_length, sizeof(flags_length));
475 
476   frame.WriteBytes(data, len);
477   scoped_ptr<SpdyFrame> data_frame(frame.take());
478   SpdyDataFrame* rv;
479   if (flags & DATA_FLAG_COMPRESSED) {
480     rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get()));
481   } else {
482     rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
483   }
484 
485   if (flags & DATA_FLAG_FIN) {
486     CleanupCompressorForStream(stream_id);
487   }
488 
489   return rv;
490 }
491 
CompressFrame(const SpdyFrame & frame)492 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) {
493   if (frame.is_control_frame()) {
494     return CompressControlFrame(
495         reinterpret_cast<const SpdyControlFrame&>(frame));
496   }
497   return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
498 }
499 
DecompressFrame(const SpdyFrame & frame)500 SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) {
501   if (frame.is_control_frame()) {
502     return DecompressControlFrame(
503         reinterpret_cast<const SpdyControlFrame&>(frame));
504   }
505   return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
506 }
507 
DuplicateFrame(const SpdyFrame & frame)508 SpdyFrame* SpdyFramer::DuplicateFrame(const SpdyFrame& frame) {
509   int size = SpdyFrame::size() + frame.length();
510   SpdyFrame* new_frame = new SpdyFrame(size);
511   memcpy(new_frame->data(), frame.data(), size);
512   return new_frame;
513 }
514 
IsCompressible(const SpdyFrame & frame) const515 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const {
516   // The important frames to compress are those which contain large
517   // amounts of compressible data - namely the headers in the SYN_STREAM
518   // and SYN_REPLY.
519   // TODO(mbelshe): Reconcile this with the spec when the spec is
520   // explicit about which frames compress and which do not.
521   if (frame.is_control_frame()) {
522     const SpdyControlFrame& control_frame =
523         reinterpret_cast<const SpdyControlFrame&>(frame);
524     return control_frame.type() == SYN_STREAM ||
525            control_frame.type() == SYN_REPLY;
526   }
527 
528   const SpdyDataFrame& data_frame =
529       reinterpret_cast<const SpdyDataFrame&>(frame);
530   return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0;
531 }
532 
StateToString(int state)533 const char* SpdyFramer::StateToString(int state) {
534   switch (state) {
535     case SPDY_ERROR:
536       return "ERROR";
537     case SPDY_DONE:
538       return "DONE";
539     case SPDY_AUTO_RESET:
540       return "AUTO_RESET";
541     case SPDY_RESET:
542       return "RESET";
543     case SPDY_READING_COMMON_HEADER:
544       return "READING_COMMON_HEADER";
545     case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
546       return "INTERPRET_CONTROL_FRAME_COMMON_HEADER";
547     case SPDY_CONTROL_FRAME_PAYLOAD:
548       return "CONTROL_FRAME_PAYLOAD";
549     case SPDY_IGNORE_REMAINING_PAYLOAD:
550       return "IGNORE_REMAINING_PAYLOAD";
551     case SPDY_FORWARD_STREAM_FRAME:
552       return "FORWARD_STREAM_FRAME";
553   }
554   return "UNKNOWN_STATE";
555 }
556 
ErrorCodeToString(int error_code)557 const char* SpdyFramer::ErrorCodeToString(int error_code) {
558   switch (error_code) {
559     case SPDY_NO_ERROR:
560       return "NO_ERROR";
561     case SPDY_INVALID_CONTROL_FRAME:
562       return "INVALID_CONTROL_FRAME";
563     case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
564       return "CONTROL_PAYLOAD_TOO_LARGE";
565     case SPDY_ZLIB_INIT_FAILURE:
566       return "ZLIB_INIT_FAILURE";
567     case SPDY_UNSUPPORTED_VERSION:
568       return "UNSUPPORTED_VERSION";
569     case SPDY_DECOMPRESS_FAILURE:
570       return "DECOMPRESS_FAILURE";
571     case SPDY_COMPRESS_FAILURE:
572       return "COMPRESS_FAILURE";
573   }
574   return "UNKNOWN_ERROR";
575 }
576 
set_enable_compression(bool value)577 void SpdyFramer::set_enable_compression(bool value) {
578   enable_compression_ = value;
579 }
580 
set_enable_compression_default(bool value)581 void SpdyFramer::set_enable_compression_default(bool value) {
582   compression_default_ = value;
583 }
584 
ProcessCommonHeader(const char * data,size_t len)585 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
586   // This should only be called when we're in the SPDY_READING_COMMON_HEADER
587   // state.
588   DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
589 
590   size_t original_len = len;
591   SpdyFrame current_frame(current_frame_buffer_, false);
592 
593   do {
594     if (current_frame_len_ < SpdyFrame::size()) {
595       size_t bytes_desired = SpdyFrame::size() - current_frame_len_;
596       size_t bytes_to_append = std::min(bytes_desired, len);
597       char* header_buffer = current_frame_buffer_;
598       memcpy(&header_buffer[current_frame_len_], data, bytes_to_append);
599       current_frame_len_ += bytes_to_append;
600       data += bytes_to_append;
601       len -= bytes_to_append;
602       // Check for an empty data frame.
603       if (current_frame_len_ == SpdyFrame::size() &&
604           !current_frame.is_control_frame() &&
605           current_frame.length() == 0) {
606         if (current_frame.flags() & CONTROL_FLAG_FIN) {
607           SpdyDataFrame data_frame(current_frame_buffer_, false);
608           visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
609         }
610         CHANGE_STATE(SPDY_AUTO_RESET);
611       }
612       break;
613     }
614     remaining_payload_ = current_frame.length();
615 
616     // This is just a sanity check for help debugging early frame errors.
617     if (remaining_payload_ > 1000000u) {
618       LOG(WARNING) <<
619           "Unexpectedly large frame.  Spdy session is likely corrupt.";
620     }
621 
622     // if we're here, then we have the common header all received.
623     if (!current_frame.is_control_frame())
624       CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
625     else
626       CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER);
627   } while (false);
628 
629   return original_len - len;
630 }
631 
ProcessControlFrameHeader()632 void SpdyFramer::ProcessControlFrameHeader() {
633   DCHECK_EQ(SPDY_NO_ERROR, error_code_);
634   DCHECK_LE(SpdyFrame::size(), current_frame_len_);
635   SpdyControlFrame current_control_frame(current_frame_buffer_, false);
636 
637   // We check version before we check validity: version can never be 'invalid',
638   // it can only be unsupported.
639   if (current_control_frame.version() != spdy_version_) {
640     set_error(SPDY_UNSUPPORTED_VERSION);
641     return;
642   }
643 
644   // Next up, check to see if we have valid data.  This should be after version
645   // checking (otherwise if the the type were out of bounds due to a version
646   // upgrade we would misclassify the error) and before checking the type
647   // (type can definitely be out of bounds)
648   if (!current_control_frame.AppearsToBeAValidControlFrame()) {
649     set_error(SPDY_INVALID_CONTROL_FRAME);
650     return;
651   }
652 
653   // Do some sanity checking on the control frame sizes.
654   switch (current_control_frame.type()) {
655     case SYN_STREAM:
656       if (current_control_frame.length() <
657           SpdySynStreamControlFrame::size() - SpdyControlFrame::size())
658         set_error(SPDY_INVALID_CONTROL_FRAME);
659       break;
660     case SYN_REPLY:
661       if (current_control_frame.length() <
662           SpdySynReplyControlFrame::size() - SpdyControlFrame::size())
663         set_error(SPDY_INVALID_CONTROL_FRAME);
664       break;
665     case RST_STREAM:
666       if (current_control_frame.length() !=
667           SpdyRstStreamControlFrame::size() - SpdyFrame::size())
668         set_error(SPDY_INVALID_CONTROL_FRAME);
669       break;
670     case SETTINGS:
671       if (current_control_frame.length() <
672           SpdySettingsControlFrame::size() - SpdyControlFrame::size())
673         set_error(SPDY_INVALID_CONTROL_FRAME);
674       break;
675     case NOOP:
676       // NOOP.  Swallow it.
677       CHANGE_STATE(SPDY_AUTO_RESET);
678       return;
679     case GOAWAY:
680       if (current_control_frame.length() !=
681           SpdyGoAwayControlFrame::size() - SpdyFrame::size())
682         set_error(SPDY_INVALID_CONTROL_FRAME);
683       break;
684     case HEADERS:
685       if (current_control_frame.length() <
686           SpdyHeadersControlFrame::size() - SpdyControlFrame::size())
687         set_error(SPDY_INVALID_CONTROL_FRAME);
688       break;
689     case WINDOW_UPDATE:
690       if (current_control_frame.length() !=
691           SpdyWindowUpdateControlFrame::size() - SpdyControlFrame::size())
692         set_error(SPDY_INVALID_CONTROL_FRAME);
693       break;
694     default:
695       LOG(WARNING) << "Valid spdy control frame with unknown type: "
696                    << current_control_frame.type();
697       DCHECK(false);
698       set_error(SPDY_INVALID_CONTROL_FRAME);
699       break;
700   }
701 
702   remaining_control_payload_ = current_control_frame.length();
703   if (remaining_control_payload_ > kControlFrameBufferMaxSize) {
704     set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
705     return;
706   }
707 
708   ExpandControlFrameBuffer(remaining_control_payload_);
709   CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
710 }
711 
ProcessControlFramePayload(const char * data,size_t len)712 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
713   size_t original_len = len;
714   do {
715     if (remaining_control_payload_) {
716       size_t amount_to_consume = std::min(remaining_control_payload_, len);
717       memcpy(&current_frame_buffer_[current_frame_len_], data,
718              amount_to_consume);
719       current_frame_len_ += amount_to_consume;
720       data += amount_to_consume;
721       len -= amount_to_consume;
722       remaining_control_payload_ -= amount_to_consume;
723       remaining_payload_ -= amount_to_consume;
724       if (remaining_control_payload_)
725         break;
726     }
727     SpdyControlFrame control_frame(current_frame_buffer_, false);
728     visitor_->OnControl(&control_frame);
729 
730     // If this is a FIN, tell the caller.
731     if (control_frame.type() == SYN_REPLY &&
732         control_frame.flags() & CONTROL_FLAG_FIN) {
733       visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>(
734                                       &control_frame)->stream_id(),
735                                   NULL, 0);
736     }
737 
738     CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
739   } while (false);
740   return original_len - len;
741 }
742 
ProcessDataFramePayload(const char * data,size_t len)743 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
744   size_t original_len = len;
745 
746   SpdyDataFrame current_data_frame(current_frame_buffer_, false);
747   if (remaining_payload_) {
748     size_t amount_to_forward = std::min(remaining_payload_, len);
749     if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
750       if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) {
751         z_stream* decompressor =
752             GetStreamDecompressor(current_data_frame.stream_id());
753         if (!decompressor)
754           return 0;
755 
756         size_t decompressed_max_size = amount_to_forward * 100;
757         scoped_array<char> decompressed(new char[decompressed_max_size]);
758         decompressor->next_in = reinterpret_cast<Bytef*>(
759             const_cast<char*>(data));
760         decompressor->avail_in = amount_to_forward;
761         decompressor->next_out =
762             reinterpret_cast<Bytef*>(decompressed.get());
763         decompressor->avail_out = decompressed_max_size;
764 
765         int rv = inflate(decompressor, Z_SYNC_FLUSH);
766         if (rv != Z_OK) {
767           LOG(WARNING) << "inflate failure: " << rv;
768           set_error(SPDY_DECOMPRESS_FAILURE);
769           return 0;
770         }
771         size_t decompressed_size = decompressed_max_size -
772                                    decompressor->avail_out;
773 
774         // Only inform the visitor if there is data.
775         if (decompressed_size)
776           visitor_->OnStreamFrameData(current_data_frame.stream_id(),
777                                       decompressed.get(),
778                                       decompressed_size);
779         amount_to_forward -= decompressor->avail_in;
780       } else {
781         // The data frame was not compressed.
782         // Only inform the visitor if there is data.
783         if (amount_to_forward)
784           visitor_->OnStreamFrameData(current_data_frame.stream_id(),
785                                       data, amount_to_forward);
786       }
787     }
788     data += amount_to_forward;
789     len -= amount_to_forward;
790     remaining_payload_ -= amount_to_forward;
791 
792     // If the FIN flag is set, and there is no more data in this data
793     // frame, inform the visitor of EOF via a 0-length data frame.
794     if (!remaining_payload_ &&
795         current_data_frame.flags() & DATA_FLAG_FIN) {
796       visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0);
797       CleanupDecompressorForStream(current_data_frame.stream_id());
798     }
799   } else {
800     CHANGE_STATE(SPDY_AUTO_RESET);
801   }
802   return original_len - len;
803 }
804 
GetHeaderCompressor()805 z_stream* SpdyFramer::GetHeaderCompressor() {
806   if (header_compressor_.get())
807     return header_compressor_.get();  // Already initialized.
808 
809   header_compressor_.reset(new z_stream);
810   memset(header_compressor_.get(), 0, sizeof(z_stream));
811 
812   int success = deflateInit2(header_compressor_.get(),
813                              kCompressorLevel,
814                              Z_DEFLATED,
815                              kCompressorWindowSizeInBits,
816                              kCompressorMemLevel,
817                              Z_DEFAULT_STRATEGY);
818   if (success == Z_OK)
819     success = deflateSetDictionary(header_compressor_.get(),
820                                    reinterpret_cast<const Bytef*>(kDictionary),
821                                    kDictionarySize);
822   if (success != Z_OK) {
823     LOG(WARNING) << "deflateSetDictionary failure: " << success;
824     header_compressor_.reset(NULL);
825     return NULL;
826   }
827   return header_compressor_.get();
828 }
829 
GetHeaderDecompressor()830 z_stream* SpdyFramer::GetHeaderDecompressor() {
831   if (header_decompressor_.get())
832     return header_decompressor_.get();  // Already initialized.
833 
834   header_decompressor_.reset(new z_stream);
835   memset(header_decompressor_.get(), 0, sizeof(z_stream));
836 
837   // Compute the id of our dictionary so that we know we're using the
838   // right one when asked for it.
839   if (dictionary_id == 0) {
840     dictionary_id = adler32(0L, Z_NULL, 0);
841     dictionary_id = adler32(dictionary_id,
842                             reinterpret_cast<const Bytef*>(kDictionary),
843                             kDictionarySize);
844   }
845 
846   int success = inflateInit(header_decompressor_.get());
847   if (success != Z_OK) {
848     LOG(WARNING) << "inflateInit failure: " << success;
849     header_decompressor_.reset(NULL);
850     return NULL;
851   }
852   return header_decompressor_.get();
853 }
854 
GetStreamCompressor(SpdyStreamId stream_id)855 z_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) {
856   CompressorMap::iterator it = stream_compressors_.find(stream_id);
857   if (it != stream_compressors_.end())
858     return it->second;  // Already initialized.
859 
860   scoped_ptr<z_stream> compressor(new z_stream);
861   memset(compressor.get(), 0, sizeof(z_stream));
862 
863   int success = deflateInit2(compressor.get(),
864                              kCompressorLevel,
865                              Z_DEFLATED,
866                              kCompressorWindowSizeInBits,
867                              kCompressorMemLevel,
868                              Z_DEFAULT_STRATEGY);
869   if (success != Z_OK) {
870     LOG(WARNING) << "deflateInit failure: " << success;
871     return NULL;
872   }
873   return stream_compressors_[stream_id] = compressor.release();
874 }
875 
GetStreamDecompressor(SpdyStreamId stream_id)876 z_stream* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id) {
877   CompressorMap::iterator it = stream_decompressors_.find(stream_id);
878   if (it != stream_decompressors_.end())
879     return it->second;  // Already initialized.
880 
881   scoped_ptr<z_stream> decompressor(new z_stream);
882   memset(decompressor.get(), 0, sizeof(z_stream));
883 
884   int success = inflateInit(decompressor.get());
885   if (success != Z_OK) {
886     LOG(WARNING) << "inflateInit failure: " << success;
887     return NULL;
888   }
889   return stream_decompressors_[stream_id] = decompressor.release();
890 }
891 
CompressControlFrame(const SpdyControlFrame & frame)892 SpdyControlFrame* SpdyFramer::CompressControlFrame(
893     const SpdyControlFrame& frame) {
894   z_stream* compressor = GetHeaderCompressor();
895   if (!compressor)
896     return NULL;
897   return reinterpret_cast<SpdyControlFrame*>(
898       CompressFrameWithZStream(frame, compressor));
899 }
900 
CompressDataFrame(const SpdyDataFrame & frame)901 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
902   z_stream* compressor = GetStreamCompressor(frame.stream_id());
903   if (!compressor)
904     return NULL;
905   return reinterpret_cast<SpdyDataFrame*>(
906       CompressFrameWithZStream(frame, compressor));
907 }
908 
DecompressControlFrame(const SpdyControlFrame & frame)909 SpdyControlFrame* SpdyFramer::DecompressControlFrame(
910     const SpdyControlFrame& frame) {
911   z_stream* decompressor = GetHeaderDecompressor();
912   if (!decompressor)
913     return NULL;
914   return reinterpret_cast<SpdyControlFrame*>(
915       DecompressFrameWithZStream(frame, decompressor));
916 }
917 
DecompressDataFrame(const SpdyDataFrame & frame)918 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) {
919   z_stream* decompressor = GetStreamDecompressor(frame.stream_id());
920   if (!decompressor)
921     return NULL;
922   return reinterpret_cast<SpdyDataFrame*>(
923       DecompressFrameWithZStream(frame, decompressor));
924 }
925 
CompressFrameWithZStream(const SpdyFrame & frame,z_stream * compressor)926 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame,
927                                                 z_stream* compressor) {
928   int payload_length;
929   int header_length;
930   const char* payload;
931 
932   base::StatsCounter compressed_frames("spdy.CompressedFrames");
933   base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
934   base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
935 
936   if (!enable_compression_)
937     return DuplicateFrame(frame);
938 
939   if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload))
940     return NULL;
941 
942   // Create an output frame.
943   int compressed_max_size = deflateBound(compressor, payload_length);
944   int new_frame_size = header_length + compressed_max_size;
945   scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size));
946   memcpy(new_frame->data(), frame.data(), frame.length() + SpdyFrame::size());
947 
948   compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
949   compressor->avail_in = payload_length;
950   compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
951                           header_length;
952   compressor->avail_out = compressed_max_size;
953 
954   // Data packets have a 'compressed' flag.
955   if (!new_frame->is_control_frame()) {
956     SpdyDataFrame* data_frame =
957         reinterpret_cast<SpdyDataFrame*>(new_frame.get());
958     data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED);
959   }
960 
961 #ifndef ANDROID
962   // Make sure that all the data we pass to zlib is defined.
963   // This way, all Valgrind reports on the compressed data are zlib's fault.
964   (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in,
965                                       compressor->avail_in);
966 #endif
967 
968   int rv = deflate(compressor, Z_SYNC_FLUSH);
969   if (rv != Z_OK) {  // How can we know that it compressed everything?
970     // This shouldn't happen, right?
971     LOG(WARNING) << "deflate failure: " << rv;
972     return NULL;
973   }
974 
975   int compressed_size = compressed_max_size - compressor->avail_out;
976 
977 #ifndef ANDROID
978   // We trust zlib. Also, we can't do anything about it.
979   // See http://www.zlib.net/zlib_faq.html#faq36
980   (void)VALGRIND_MAKE_MEM_DEFINED(new_frame->data() + header_length,
981                                   compressed_size);
982 #endif
983 
984   new_frame->set_length(header_length + compressed_size - SpdyFrame::size());
985 
986   pre_compress_bytes.Add(payload_length);
987   post_compress_bytes.Add(new_frame->length());
988 
989   compressed_frames.Increment();
990 
991   return new_frame.release();
992 }
993 
DecompressFrameWithZStream(const SpdyFrame & frame,z_stream * decompressor)994 SpdyFrame* SpdyFramer::DecompressFrameWithZStream(const SpdyFrame& frame,
995                                                   z_stream* decompressor) {
996   int payload_length;
997   int header_length;
998   const char* payload;
999 
1000   base::StatsCounter decompressed_frames("spdy.DecompressedFrames");
1001   base::StatsCounter pre_decompress_bytes("spdy.PreDeCompressSize");
1002   base::StatsCounter post_decompress_bytes("spdy.PostDeCompressSize");
1003 
1004   if (!enable_compression_)
1005     return DuplicateFrame(frame);
1006 
1007   if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload))
1008     return NULL;
1009 
1010   if (!frame.is_control_frame()) {
1011     const SpdyDataFrame& data_frame =
1012         reinterpret_cast<const SpdyDataFrame&>(frame);
1013     if ((data_frame.flags() & DATA_FLAG_COMPRESSED) == 0)
1014       return DuplicateFrame(frame);
1015   }
1016 
1017   // Create an output frame.  Assume it does not need to be longer than
1018   // the input data.
1019   size_t decompressed_max_size = kControlFrameBufferInitialSize;
1020   int new_frame_size = header_length + decompressed_max_size;
1021   if (frame.length() > decompressed_max_size)
1022     return NULL;
1023   scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size));
1024   memcpy(new_frame->data(), frame.data(), frame.length() + SpdyFrame::size());
1025 
1026   decompressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
1027   decompressor->avail_in = payload_length;
1028   decompressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
1029       header_length;
1030   decompressor->avail_out = decompressed_max_size;
1031 
1032   int rv = inflate(decompressor, Z_SYNC_FLUSH);
1033   if (rv == Z_NEED_DICT) {
1034     // Need to try again with the right dictionary.
1035     if (decompressor->adler == dictionary_id) {
1036       rv = inflateSetDictionary(decompressor, (const Bytef*)kDictionary,
1037                                 kDictionarySize);
1038       if (rv == Z_OK)
1039         rv = inflate(decompressor, Z_SYNC_FLUSH);
1040     }
1041   }
1042   if (rv != Z_OK) {  // How can we know that it decompressed everything?
1043     LOG(WARNING) << "inflate failure: " << rv;
1044     return NULL;
1045   }
1046 
1047   // Unset the compressed flag for data frames.
1048   if (!new_frame->is_control_frame()) {
1049     SpdyDataFrame* data_frame =
1050         reinterpret_cast<SpdyDataFrame*>(new_frame.get());
1051     data_frame->set_flags(data_frame->flags() & ~DATA_FLAG_COMPRESSED);
1052   }
1053 
1054   int decompressed_size = decompressed_max_size - decompressor->avail_out;
1055   new_frame->set_length(header_length + decompressed_size - SpdyFrame::size());
1056 
1057   // If there is data left, then the frame didn't fully decompress.  This
1058   // means that there is stranded data at the end of this frame buffer which
1059   // will be ignored.
1060   DCHECK_EQ(decompressor->avail_in, 0u);
1061 
1062   pre_decompress_bytes.Add(frame.length());
1063   post_decompress_bytes.Add(new_frame->length());
1064 
1065   decompressed_frames.Increment();
1066 
1067   return new_frame.release();
1068 }
1069 
CleanupCompressorForStream(SpdyStreamId id)1070 void SpdyFramer::CleanupCompressorForStream(SpdyStreamId id) {
1071   CompressorMap::iterator it = stream_compressors_.find(id);
1072   if (it != stream_compressors_.end()) {
1073     z_stream* compressor = it->second;
1074     deflateEnd(compressor);
1075     delete compressor;
1076     stream_compressors_.erase(it);
1077   }
1078 }
1079 
CleanupDecompressorForStream(SpdyStreamId id)1080 void SpdyFramer::CleanupDecompressorForStream(SpdyStreamId id) {
1081   CompressorMap::iterator it = stream_decompressors_.find(id);
1082   if (it != stream_decompressors_.end()) {
1083     z_stream* decompressor = it->second;
1084     inflateEnd(decompressor);
1085     delete decompressor;
1086     stream_decompressors_.erase(it);
1087   }
1088 }
1089 
CleanupStreamCompressorsAndDecompressors()1090 void SpdyFramer::CleanupStreamCompressorsAndDecompressors() {
1091   CompressorMap::iterator it;
1092 
1093   it = stream_compressors_.begin();
1094   while (it != stream_compressors_.end()) {
1095     z_stream* compressor = it->second;
1096     deflateEnd(compressor);
1097     delete compressor;
1098     ++it;
1099   }
1100   stream_compressors_.clear();
1101 
1102   it = stream_decompressors_.begin();
1103   while (it != stream_decompressors_.end()) {
1104     z_stream* decompressor = it->second;
1105     inflateEnd(decompressor);
1106     delete decompressor;
1107     ++it;
1108   }
1109   stream_decompressors_.clear();
1110 }
1111 
BytesSafeToRead() const1112 size_t SpdyFramer::BytesSafeToRead() const {
1113   switch (state_) {
1114     case SPDY_ERROR:
1115     case SPDY_DONE:
1116     case SPDY_AUTO_RESET:
1117     case SPDY_RESET:
1118       return 0;
1119     case SPDY_READING_COMMON_HEADER:
1120       DCHECK_LT(current_frame_len_, SpdyFrame::size());
1121       return SpdyFrame::size() - current_frame_len_;
1122     case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
1123       return 0;
1124     case SPDY_CONTROL_FRAME_PAYLOAD:
1125     case SPDY_IGNORE_REMAINING_PAYLOAD:
1126     case SPDY_FORWARD_STREAM_FRAME:
1127       return remaining_payload_;
1128   }
1129   // We should never get to here.
1130   return 0;
1131 }
1132 
set_error(SpdyError error)1133 void SpdyFramer::set_error(SpdyError error) {
1134   DCHECK(visitor_);
1135   error_code_ = error;
1136   CHANGE_STATE(SPDY_ERROR);
1137   visitor_->OnError(this);
1138 }
1139 
ExpandControlFrameBuffer(size_t size)1140 void SpdyFramer::ExpandControlFrameBuffer(size_t size) {
1141   size_t alloc_size = size + SpdyFrame::size();
1142   DCHECK_LT(alloc_size, kControlFrameBufferMaxSize);
1143   if (alloc_size <= current_frame_capacity_)
1144     return;
1145   char* new_buffer = new char[alloc_size];
1146   memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
1147   delete [] current_frame_buffer_;
1148   current_frame_capacity_ = alloc_size;
1149   current_frame_buffer_ = new_buffer;
1150 }
1151 
GetFrameBoundaries(const SpdyFrame & frame,int * payload_length,int * header_length,const char ** payload) const1152 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame,
1153                                     int* payload_length,
1154                                     int* header_length,
1155                                     const char** payload) const {
1156   size_t frame_size;
1157   if (frame.is_control_frame()) {
1158     const SpdyControlFrame& control_frame =
1159         reinterpret_cast<const SpdyControlFrame&>(frame);
1160     switch (control_frame.type()) {
1161       case SYN_STREAM:
1162         {
1163           const SpdySynStreamControlFrame& syn_frame =
1164               reinterpret_cast<const SpdySynStreamControlFrame&>(frame);
1165           frame_size = SpdySynStreamControlFrame::size();
1166           *payload_length = syn_frame.header_block_len();
1167           *header_length = frame_size;
1168           *payload = frame.data() + *header_length;
1169         }
1170         break;
1171       case SYN_REPLY:
1172         {
1173           const SpdySynReplyControlFrame& syn_frame =
1174               reinterpret_cast<const SpdySynReplyControlFrame&>(frame);
1175           frame_size = SpdySynReplyControlFrame::size();
1176           *payload_length = syn_frame.header_block_len();
1177           *header_length = frame_size;
1178           *payload = frame.data() + *header_length;
1179         }
1180         break;
1181       case HEADERS:
1182         {
1183           const SpdyHeadersControlFrame& headers_frame =
1184               reinterpret_cast<const SpdyHeadersControlFrame&>(frame);
1185           frame_size = SpdyHeadersControlFrame::size();
1186           *payload_length = headers_frame.header_block_len();
1187           *header_length = frame_size;
1188           *payload = frame.data() + *header_length;
1189         }
1190         break;
1191       default:
1192         // TODO(mbelshe): set an error?
1193         return false;  // We can't compress this frame!
1194     }
1195   } else {
1196     frame_size = SpdyFrame::size();
1197     *header_length = frame_size;
1198     *payload_length = frame.length();
1199     *payload = frame.data() + SpdyFrame::size();
1200   }
1201   return true;
1202 }
1203 
1204 }  // namespace spdy
1205