• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/spdy/spdy_framer.h"
6 
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/stats_counters.h"
10 #include "base/third_party/valgrind/memcheck.h"
11 #include "net/spdy/spdy_frame_builder.h"
12 #include "net/spdy/spdy_frame_reader.h"
13 #include "net/spdy/spdy_bitmasks.h"
14 #include "third_party/zlib/zlib.h"
15 
16 using base::StringPiece;
17 using std::string;
18 using std::vector;
19 
20 namespace net {
21 
22 namespace {
23 
24 // Compute the id of our dictionary so that we know we're using the
25 // right one when asked for it.
CalculateDictionaryId(const char * dictionary,const size_t dictionary_size)26 uLong CalculateDictionaryId(const char* dictionary,
27                             const size_t dictionary_size) {
28   uLong initial_value = adler32(0L, Z_NULL, 0);
29   return adler32(initial_value,
30                  reinterpret_cast<const Bytef*>(dictionary),
31                  dictionary_size);
32 }
33 
34 struct DictionaryIds {
DictionaryIdsnet::__anon1f0272040111::DictionaryIds35   DictionaryIds()
36     : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
37       v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
38   {}
39   const uLong v2_dictionary_id;
40   const uLong v3_dictionary_id;
41 };
42 
43 // Adler ID for the SPDY header compressor dictionaries. Note that they are
44 // initialized lazily to avoid static initializers.
45 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
46 
47 // Used to indicate no flags in a SPDY flags field.
48 const uint8 kNoFlags = 0;
49 
50 // Wire sizes of priority payloads.
51 const size_t kPriorityDependencyPayloadSize = 4;
52 const size_t kPriorityWeightPayloadSize = 1;
53 
54 }  // namespace
55 
56 const SpdyStreamId SpdyFramer::kInvalidStream = -1;
57 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
58 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
59 // calculation details.
60 const size_t SpdyFramer::kControlFrameBufferSize = 18;
61 
62 #ifdef DEBUG_SPDY_STATE_CHANGES
63 #define CHANGE_STATE(newstate)                                  \
64   do {                                                          \
65     DVLOG(1) << "Changing state from: "                         \
66              << StateToString(state_)                           \
67              << " to " << StateToString(newstate) << "\n";      \
68     DCHECK(state_ != SPDY_ERROR);                               \
69     DCHECK_EQ(previous_state_, state_);                         \
70     previous_state_ = state_;                                   \
71     state_ = newstate;                                          \
72   } while (false)
73 #else
74 #define CHANGE_STATE(newstate)                                  \
75   do {                                                          \
76     DCHECK(state_ != SPDY_ERROR);                               \
77     DCHECK_EQ(previous_state_, state_);                         \
78     previous_state_ = state_;                                   \
79     state_ = newstate;                                          \
80   } while (false)
81 #endif
82 
FromWireFormat(SpdyMajorVersion version,uint32 wire)83 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(
84     SpdyMajorVersion version, uint32 wire) {
85   if (version < SPDY3) {
86     ConvertFlagsAndIdForSpdy2(&wire);
87   }
88   return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
89 }
90 
SettingsFlagsAndId(uint8 flags,uint32 id)91 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
92     : flags_(flags), id_(id & 0x00ffffff) {
93   LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
94 }
95 
GetWireFormat(SpdyMajorVersion version) const96 uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version)
97     const {
98   uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
99   if (version < SPDY3) {
100     ConvertFlagsAndIdForSpdy2(&wire);
101   }
102   return wire;
103 }
104 
105 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
106 // This method is used to preserve buggy behavior and works on both
107 // little-endian and big-endian hosts.
108 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
109 // as well as vice versa).
ConvertFlagsAndIdForSpdy2(uint32 * val)110 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
111     uint8* wire_array = reinterpret_cast<uint8*>(val);
112     std::swap(wire_array[0], wire_array[3]);
113     std::swap(wire_array[1], wire_array[2]);
114 }
115 
SpdyAltSvcScratch()116 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
~SpdyAltSvcScratch()117 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
118 
OnGoAwayFrameData(const char * goaway_data,size_t len)119 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
120                                                    size_t len) {
121   return true;
122 }
123 
OnRstStreamFrameData(const char * rst_stream_data,size_t len)124 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
125     const char* rst_stream_data,
126     size_t len) {
127   return true;
128 }
129 
SpdyFramer(SpdyMajorVersion version)130 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
131     : current_frame_buffer_(new char[kControlFrameBufferSize]),
132       enable_compression_(true),
133       visitor_(NULL),
134       debug_visitor_(NULL),
135       display_protocol_("SPDY"),
136       spdy_version_(version),
137       syn_frame_processed_(false),
138       probable_http_response_(false),
139       expect_continuation_(0),
140       end_stream_when_done_(false) {
141   DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
142   DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
143   Reset();
144 }
145 
~SpdyFramer()146 SpdyFramer::~SpdyFramer() {
147   if (header_compressor_.get()) {
148     deflateEnd(header_compressor_.get());
149   }
150   if (header_decompressor_.get()) {
151     inflateEnd(header_decompressor_.get());
152   }
153 }
154 
Reset()155 void SpdyFramer::Reset() {
156   state_ = SPDY_RESET;
157   previous_state_ = SPDY_RESET;
158   error_code_ = SPDY_NO_ERROR;
159   remaining_data_length_ = 0;
160   remaining_control_header_ = 0;
161   current_frame_buffer_length_ = 0;
162   current_frame_type_ = DATA;
163   current_frame_flags_ = 0;
164   current_frame_length_ = 0;
165   current_frame_stream_id_ = kInvalidStream;
166   settings_scratch_.Reset();
167   altsvc_scratch_.Reset();
168   remaining_padding_payload_length_ = 0;
169   remaining_padding_length_fields_ = 0;
170 }
171 
GetDataFrameMinimumSize() const172 size_t SpdyFramer::GetDataFrameMinimumSize() const {
173   return SpdyConstants::GetDataFrameMinimumSize();
174 }
175 
176 // Size, in bytes, of the control frame header.
GetControlFrameHeaderSize() const177 size_t SpdyFramer::GetControlFrameHeaderSize() const {
178   return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
179 }
180 
GetSynStreamMinimumSize() const181 size_t SpdyFramer::GetSynStreamMinimumSize() const {
182   // Size, in bytes, of a SYN_STREAM frame not including the variable-length
183   // name-value block.
184   if (protocol_version() <= SPDY3) {
185     // Calculated as:
186     // control frame header + 2 * 4 (stream IDs) + 1 (priority)
187     // + 1 (unused, was credential slot)
188     return GetControlFrameHeaderSize() + 10;
189   } else {
190     return GetControlFrameHeaderSize() +
191         kPriorityDependencyPayloadSize +
192         kPriorityWeightPayloadSize;
193   }
194 }
195 
GetSynReplyMinimumSize() const196 size_t SpdyFramer::GetSynReplyMinimumSize() const {
197   // Size, in bytes, of a SYN_REPLY frame not including the variable-length
198   // name-value block.
199   size_t size = GetControlFrameHeaderSize();
200   if (protocol_version() <= SPDY3) {
201     // Calculated as:
202     // control frame header + 4 (stream IDs)
203     size += 4;
204   }
205 
206   // In SPDY 2, there were 2 unused bytes before payload.
207   if (protocol_version() < SPDY3) {
208     size += 2;
209   }
210 
211   return size;
212 }
213 
GetRstStreamMinimumSize() const214 size_t SpdyFramer::GetRstStreamMinimumSize() const {
215   // Size, in bytes, of a RST_STREAM frame.
216   if (protocol_version() <= SPDY3) {
217     // Calculated as:
218     // control frame header + 4 (stream id) + 4 (status code)
219     return GetControlFrameHeaderSize() + 8;
220   } else {
221     // Calculated as:
222     // frame prefix + 4 (status code)
223     return GetControlFrameHeaderSize() + 4;
224   }
225 }
226 
GetSettingsMinimumSize() const227 size_t SpdyFramer::GetSettingsMinimumSize() const {
228   // Size, in bytes, of a SETTINGS frame not including the IDs and values
229   // from the variable-length value block. Calculated as:
230   // control frame header + 4 (number of ID/value pairs)
231   if (protocol_version() <= SPDY3) {
232     return GetControlFrameHeaderSize() + 4;
233   } else {
234     return GetControlFrameHeaderSize();
235   }
236 }
237 
GetPingSize() const238 size_t SpdyFramer::GetPingSize() const {
239   // Size, in bytes, of this PING frame.
240   if (protocol_version() <= SPDY3) {
241     // Calculated as:
242     // control frame header + 4 (id)
243     return GetControlFrameHeaderSize() + 4;
244   } else {
245     // Calculated as:
246     // control frame header + 8 (id)
247     return GetControlFrameHeaderSize() + 8;
248   }
249 }
250 
GetGoAwayMinimumSize() const251 size_t SpdyFramer::GetGoAwayMinimumSize() const {
252   // Size, in bytes, of this GOAWAY frame. Calculated as:
253   // 1. Control frame header size
254   size_t size = GetControlFrameHeaderSize();
255 
256   // 2. Last good stream id (4 bytes)
257   size += 4;
258 
259   // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
260   if (protocol_version() >= SPDY3) {
261     size += 4;
262   }
263 
264   return size;
265 }
266 
GetHeadersMinimumSize() const267 size_t SpdyFramer::GetHeadersMinimumSize() const  {
268   // Size, in bytes, of a HEADERS frame not including the variable-length
269   // name-value block.
270   size_t size = GetControlFrameHeaderSize();
271   if (protocol_version() <= SPDY3) {
272     // Calculated as:
273     // control frame header + 4 (stream IDs)
274     size += 4;
275   }
276 
277   // In SPDY 2, there were 2 unused bytes before payload.
278   if (protocol_version() <= SPDY2) {
279     size += 2;
280   }
281 
282   return size;
283 }
284 
GetWindowUpdateSize() const285 size_t SpdyFramer::GetWindowUpdateSize() const {
286   // Size, in bytes, of a WINDOW_UPDATE frame.
287   if (protocol_version() <= SPDY3) {
288     // Calculated as:
289     // control frame header + 4 (stream id) + 4 (delta)
290     return GetControlFrameHeaderSize() + 8;
291   } else {
292     // Calculated as:
293     // frame prefix + 4 (delta)
294     return GetControlFrameHeaderSize() + 4;
295   }
296 }
297 
GetBlockedSize() const298 size_t SpdyFramer::GetBlockedSize() const {
299   DCHECK_LT(SPDY3, protocol_version());
300   // Size, in bytes, of a BLOCKED frame.
301   // The BLOCKED frame has no payload beyond the control frame header.
302   return GetControlFrameHeaderSize();
303 }
304 
GetPushPromiseMinimumSize() const305 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
306   DCHECK_LT(SPDY3, protocol_version());
307   // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
308   // Calculated as frame prefix + 4 (promised stream id).
309   return GetControlFrameHeaderSize() + 4;
310 }
311 
GetContinuationMinimumSize() const312 size_t SpdyFramer::GetContinuationMinimumSize() const {
313   // Size, in bytes, of a CONTINUATION frame not including the variable-length
314   // headers fragments.
315   return GetControlFrameHeaderSize();
316 }
317 
GetAltSvcMinimumSize() const318 size_t SpdyFramer::GetAltSvcMinimumSize() const {
319   // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
320   // (optional) Origin fields, all of which can vary in length.
321   // Note that this gives a lower bound on the frame size rather than a true
322   // minimum; the actual frame should always be larger than this.
323   // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
324   // + 1 (pid_len) + 1 (host_len).
325   return GetControlFrameHeaderSize() + 9;
326 }
327 
GetPrioritySize() const328 size_t SpdyFramer::GetPrioritySize() const {
329   // Size, in bytes, of a PRIORITY frame.
330   return GetControlFrameHeaderSize() +
331       kPriorityDependencyPayloadSize +
332       kPriorityWeightPayloadSize;
333 }
334 
GetFrameMinimumSize() const335 size_t SpdyFramer::GetFrameMinimumSize() const {
336   return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
337 }
338 
GetFrameMaximumSize() const339 size_t SpdyFramer::GetFrameMaximumSize() const {
340   return SpdyConstants::GetFrameMaximumSize(protocol_version());
341 }
342 
GetDataFrameMaximumPayload() const343 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
344   return GetFrameMaximumSize() - GetDataFrameMinimumSize();
345 }
346 
GetPrefixLength(SpdyFrameType type) const347 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
348   return SpdyConstants::GetPrefixLength(type, protocol_version());
349 }
350 
StateToString(int state)351 const char* SpdyFramer::StateToString(int state) {
352   switch (state) {
353     case SPDY_ERROR:
354       return "ERROR";
355     case SPDY_AUTO_RESET:
356       return "AUTO_RESET";
357     case SPDY_RESET:
358       return "RESET";
359     case SPDY_READING_COMMON_HEADER:
360       return "READING_COMMON_HEADER";
361     case SPDY_CONTROL_FRAME_PAYLOAD:
362       return "CONTROL_FRAME_PAYLOAD";
363     case SPDY_READ_PADDING_LENGTH:
364       return "SPDY_READ_PADDING_LENGTH";
365     case SPDY_CONSUME_PADDING:
366       return "SPDY_CONSUME_PADDING";
367     case SPDY_IGNORE_REMAINING_PAYLOAD:
368       return "IGNORE_REMAINING_PAYLOAD";
369     case SPDY_FORWARD_STREAM_FRAME:
370       return "FORWARD_STREAM_FRAME";
371     case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
372       return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
373     case SPDY_CONTROL_FRAME_HEADER_BLOCK:
374       return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
375     case SPDY_GOAWAY_FRAME_PAYLOAD:
376       return "SPDY_GOAWAY_FRAME_PAYLOAD";
377     case SPDY_RST_STREAM_FRAME_PAYLOAD:
378       return "SPDY_RST_STREAM_FRAME_PAYLOAD";
379     case SPDY_SETTINGS_FRAME_PAYLOAD:
380       return "SPDY_SETTINGS_FRAME_PAYLOAD";
381     case SPDY_ALTSVC_FRAME_PAYLOAD:
382       return "SPDY_ALTSVC_FRAME_PAYLOAD";
383   }
384   return "UNKNOWN_STATE";
385 }
386 
set_error(SpdyError error)387 void SpdyFramer::set_error(SpdyError error) {
388   DCHECK(visitor_);
389   error_code_ = error;
390   // These values will usually get reset once we come to the end
391   // of a header block, but if we run into an error that
392   // might not happen, so reset them here.
393   expect_continuation_ = 0;
394   end_stream_when_done_ = false;
395 
396   CHANGE_STATE(SPDY_ERROR);
397   visitor_->OnError(this);
398 }
399 
ErrorCodeToString(int error_code)400 const char* SpdyFramer::ErrorCodeToString(int error_code) {
401   switch (error_code) {
402     case SPDY_NO_ERROR:
403       return "NO_ERROR";
404     case SPDY_INVALID_CONTROL_FRAME:
405       return "INVALID_CONTROL_FRAME";
406     case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
407       return "CONTROL_PAYLOAD_TOO_LARGE";
408     case SPDY_ZLIB_INIT_FAILURE:
409       return "ZLIB_INIT_FAILURE";
410     case SPDY_UNSUPPORTED_VERSION:
411       return "UNSUPPORTED_VERSION";
412     case SPDY_DECOMPRESS_FAILURE:
413       return "DECOMPRESS_FAILURE";
414     case SPDY_COMPRESS_FAILURE:
415       return "COMPRESS_FAILURE";
416     case SPDY_INVALID_DATA_FRAME_FLAGS:
417       return "SPDY_INVALID_DATA_FRAME_FLAGS";
418     case SPDY_INVALID_CONTROL_FRAME_FLAGS:
419       return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
420     case SPDY_UNEXPECTED_FRAME:
421       return "UNEXPECTED_FRAME";
422   }
423   return "UNKNOWN_ERROR";
424 }
425 
StatusCodeToString(int status_code)426 const char* SpdyFramer::StatusCodeToString(int status_code) {
427   switch (status_code) {
428     case RST_STREAM_INVALID:
429       return "INVALID";
430     case RST_STREAM_PROTOCOL_ERROR:
431       return "PROTOCOL_ERROR";
432     case RST_STREAM_INVALID_STREAM:
433       return "INVALID_STREAM";
434     case RST_STREAM_REFUSED_STREAM:
435       return "REFUSED_STREAM";
436     case RST_STREAM_UNSUPPORTED_VERSION:
437       return "UNSUPPORTED_VERSION";
438     case RST_STREAM_CANCEL:
439       return "CANCEL";
440     case RST_STREAM_INTERNAL_ERROR:
441       return "INTERNAL_ERROR";
442     case RST_STREAM_FLOW_CONTROL_ERROR:
443       return "FLOW_CONTROL_ERROR";
444     case RST_STREAM_STREAM_IN_USE:
445       return "STREAM_IN_USE";
446     case RST_STREAM_STREAM_ALREADY_CLOSED:
447       return "STREAM_ALREADY_CLOSED";
448     case RST_STREAM_INVALID_CREDENTIALS:
449       return "INVALID_CREDENTIALS";
450     case RST_STREAM_FRAME_TOO_LARGE:
451       return "FRAME_TOO_LARGE";
452     case RST_STREAM_CONNECT_ERROR:
453       return "CONNECT_ERROR";
454     case RST_STREAM_ENHANCE_YOUR_CALM:
455       return "ENHANCE_YOUR_CALM";
456   }
457   return "UNKNOWN_STATUS";
458 }
459 
FrameTypeToString(SpdyFrameType type)460 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
461   switch (type) {
462     case DATA:
463       return "DATA";
464     case SYN_STREAM:
465       return "SYN_STREAM";
466     case SYN_REPLY:
467       return "SYN_REPLY";
468     case RST_STREAM:
469       return "RST_STREAM";
470     case SETTINGS:
471       return "SETTINGS";
472     case NOOP:
473       return "NOOP";
474     case PING:
475       return "PING";
476     case GOAWAY:
477       return "GOAWAY";
478     case HEADERS:
479       return "HEADERS";
480     case WINDOW_UPDATE:
481       return "WINDOW_UPDATE";
482     case CREDENTIAL:
483       return "CREDENTIAL";
484     case BLOCKED:
485       return "BLOCKED";
486     case PUSH_PROMISE:
487       return "PUSH_PROMISE";
488     case CONTINUATION:
489       return "CONTINUATION";
490     case ALTSVC:
491       return "ALTSVC";
492     case PRIORITY:
493       return "PRIORITY";
494   }
495   return "UNKNOWN_CONTROL_TYPE";
496 }
497 
ProcessInput(const char * data,size_t len)498 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
499   DCHECK(visitor_);
500   DCHECK(data);
501 
502   size_t original_len = len;
503   do {
504     previous_state_ = state_;
505     switch (state_) {
506       case SPDY_ERROR:
507         goto bottom;
508 
509       case SPDY_AUTO_RESET:
510       case SPDY_RESET:
511         Reset();
512         if (len > 0) {
513           CHANGE_STATE(SPDY_READING_COMMON_HEADER);
514         }
515         break;
516 
517       case SPDY_READING_COMMON_HEADER: {
518         size_t bytes_read = ProcessCommonHeader(data, len);
519         len -= bytes_read;
520         data += bytes_read;
521         break;
522       }
523 
524       case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
525         // Control frames that contain header blocks
526         // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
527         // take a different path through the state machine - they
528         // will go:
529         //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
530         //   2. SPDY_CONTROL_FRAME_HEADER_BLOCK
531         //
532         // SETTINGS frames take a slightly modified route:
533         //   1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
534         //   2. SPDY_SETTINGS_FRAME_PAYLOAD
535         //
536         //  All other control frames will use the alternate route directly to
537         //  SPDY_CONTROL_FRAME_PAYLOAD
538         int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
539         len -= bytes_read;
540         data += bytes_read;
541         break;
542       }
543 
544       case SPDY_SETTINGS_FRAME_PAYLOAD: {
545         int bytes_read = ProcessSettingsFramePayload(data, len);
546         len -= bytes_read;
547         data += bytes_read;
548         break;
549       }
550 
551       case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
552         int bytes_read = ProcessControlFrameHeaderBlock(
553             data, len, protocol_version() > SPDY3);
554         len -= bytes_read;
555         data += bytes_read;
556         break;
557       }
558 
559       case SPDY_RST_STREAM_FRAME_PAYLOAD: {
560         size_t bytes_read = ProcessRstStreamFramePayload(data, len);
561         len -= bytes_read;
562         data += bytes_read;
563         break;
564       }
565 
566       case SPDY_GOAWAY_FRAME_PAYLOAD: {
567         size_t bytes_read = ProcessGoAwayFramePayload(data, len);
568         len -= bytes_read;
569         data += bytes_read;
570         break;
571       }
572 
573       case SPDY_ALTSVC_FRAME_PAYLOAD: {
574         size_t bytes_read = ProcessAltSvcFramePayload(data, len);
575         len -= bytes_read;
576         data += bytes_read;
577         break;
578       }
579 
580       case SPDY_CONTROL_FRAME_PAYLOAD: {
581         size_t bytes_read = ProcessControlFramePayload(data, len);
582         len -= bytes_read;
583         data += bytes_read;
584         break;
585       }
586 
587       case SPDY_READ_PADDING_LENGTH: {
588         size_t bytes_read = ProcessFramePaddingLength(data, len);
589         len -= bytes_read;
590         data += bytes_read;
591         break;
592       }
593 
594       case SPDY_CONSUME_PADDING: {
595         size_t bytes_read = ProcessFramePadding(data, len);
596         len -= bytes_read;
597         data += bytes_read;
598         break;
599       }
600 
601       case SPDY_IGNORE_REMAINING_PAYLOAD: {
602         size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
603         len -= bytes_read;
604         data += bytes_read;
605         break;
606       }
607 
608       case SPDY_FORWARD_STREAM_FRAME: {
609         size_t bytes_read = ProcessDataFramePayload(data, len);
610         len -= bytes_read;
611         data += bytes_read;
612         break;
613       }
614 
615       default:
616         LOG(DFATAL) << "Invalid value for " << display_protocol_
617                     << " framer state: " << state_;
618         // This ensures that we don't infinite-loop if state_ gets an
619         // invalid value somehow, such as due to a SpdyFramer getting deleted
620         // from a callback it calls.
621         goto bottom;
622     }
623   } while (state_ != previous_state_);
624  bottom:
625   DCHECK(len == 0 || state_ == SPDY_ERROR);
626   if (current_frame_buffer_length_ == 0 &&
627       remaining_data_length_ == 0 &&
628       remaining_control_header_ == 0) {
629     DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
630         << "State: " << StateToString(state_);
631   }
632 
633   return original_len - len;
634 }
635 
ProcessCommonHeader(const char * data,size_t len)636 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
637   // This should only be called when we're in the SPDY_READING_COMMON_HEADER
638   // state.
639   DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
640 
641   size_t original_len = len;
642 
643   // Update current frame buffer as needed.
644   if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
645     size_t bytes_desired =
646         GetControlFrameHeaderSize() - current_frame_buffer_length_;
647     UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
648   }
649 
650   if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
651     // Not enough information to do anything meaningful.
652     return original_len - len;
653   }
654 
655   // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
656   // when processing DATA frames below.
657   scoped_ptr<SpdyFrameReader> reader(
658       new SpdyFrameReader(current_frame_buffer_.get(),
659                           current_frame_buffer_length_));
660 
661   uint16 version = 0;
662   bool is_control_frame = false;
663 
664   uint16 control_frame_type_field = DATA;
665   // ProcessControlFrameHeader() will set current_frame_type_ to the
666   // correct value if this is a valid control frame.
667   current_frame_type_ = DATA;
668   if (protocol_version() <= SPDY3) {
669     bool successful_read = reader->ReadUInt16(&version);
670     DCHECK(successful_read);
671     is_control_frame = (version & kControlFlagMask) != 0;
672     version &= ~kControlFlagMask;  // Only valid for control frames.
673     if (is_control_frame) {
674       // We check version before we check validity: version can never be
675       // 'invalid', it can only be unsupported.
676       if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
677           version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
678           SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
679         // Version does not match the version the framer was initialized with.
680         DVLOG(1) << "Unsupported SPDY version "
681                  << version
682                  << " (expected " << protocol_version() << ")";
683         set_error(SPDY_UNSUPPORTED_VERSION);
684         return 0;
685       } else {
686         // Convert version from wire format to SpdyMajorVersion.
687         version = SpdyConstants::ParseMajorVersion(version);
688       }
689       // We check control_frame_type_field's validity in
690       // ProcessControlFrameHeader().
691       successful_read = reader->ReadUInt16(&control_frame_type_field);
692     } else {
693       reader->Rewind();
694       successful_read = reader->ReadUInt31(&current_frame_stream_id_);
695     }
696     DCHECK(successful_read);
697 
698     successful_read = reader->ReadUInt8(&current_frame_flags_);
699     DCHECK(successful_read);
700 
701     uint32 length_field = 0;
702     successful_read = reader->ReadUInt24(&length_field);
703     DCHECK(successful_read);
704     remaining_data_length_ = length_field;
705     current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
706   } else {
707     version = protocol_version();
708     uint16 length_field = 0;
709     bool successful_read = reader->ReadUInt16(&length_field);
710     DCHECK(successful_read);
711 
712     uint8 control_frame_type_field_uint8 = DATA;
713     successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
714     DCHECK(successful_read);
715     // We check control_frame_type_field's validity in
716     // ProcessControlFrameHeader().
717     control_frame_type_field = control_frame_type_field_uint8;
718     is_control_frame = (control_frame_type_field != DATA);
719 
720     if (is_control_frame) {
721       current_frame_length_ = length_field + GetControlFrameHeaderSize();
722     } else {
723       current_frame_length_ = length_field + GetDataFrameMinimumSize();
724     }
725 
726     successful_read = reader->ReadUInt8(&current_frame_flags_);
727     DCHECK(successful_read);
728 
729     successful_read = reader->ReadUInt31(&current_frame_stream_id_);
730     DCHECK(successful_read);
731 
732     remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
733 
734     // Before we accept a DATA frame, we need to make sure we're not in the
735     // middle of processing a header block.
736     const bool is_continuation_frame = (control_frame_type_field ==
737         SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
738     if ((expect_continuation_ != 0) != is_continuation_frame) {
739       if (expect_continuation_ != 0) {
740         DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
741                     << "frame, but instead received frame type "
742                     << control_frame_type_field;
743       } else {
744         DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
745       }
746       set_error(SPDY_UNEXPECTED_FRAME);
747       return original_len - len;
748     }
749   }
750   DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
751                              : GetDataFrameMinimumSize(),
752             reader->GetBytesConsumed());
753   DCHECK_EQ(current_frame_length_,
754             remaining_data_length_ + reader->GetBytesConsumed());
755 
756   // This is just a sanity check for help debugging early frame errors.
757   if (remaining_data_length_ > 1000000u) {
758     // The strncmp for 5 is safe because we only hit this point if we
759     // have kMinCommonHeader (8) bytes
760     if (!syn_frame_processed_ &&
761         strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
762       LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
763                    << " request";
764       probable_http_response_ = true;
765     } else {
766       LOG(WARNING) << "Unexpectedly large frame.  " << display_protocol_
767                    << " session is likely corrupt.";
768     }
769   }
770 
771   // if we're here, then we have the common header all received.
772   if (!is_control_frame) {
773     if (protocol_version() > SPDY3) {
774       // Catch bogus tests sending oversized DATA frames.
775       DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
776           << "DATA frame too large for SPDY >= 4.";
777     }
778 
779     uint8 valid_data_flags = 0;
780     if (protocol_version() > SPDY3) {
781       valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
782           DATA_FLAG_PAD_LOW | DATA_FLAG_PAD_HIGH;
783     } else {
784       valid_data_flags = DATA_FLAG_FIN;
785     }
786 
787     if (current_frame_flags_ & ~valid_data_flags) {
788       set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
789     } else {
790       visitor_->OnDataFrameHeader(current_frame_stream_id_,
791                                   remaining_data_length_,
792                                   current_frame_flags_ & DATA_FLAG_FIN);
793       if (remaining_data_length_ > 0) {
794         CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
795       } else {
796         // Empty data frame.
797         if (current_frame_flags_ & DATA_FLAG_FIN) {
798           visitor_->OnStreamFrameData(
799               current_frame_stream_id_, NULL, 0, true);
800         }
801         CHANGE_STATE(SPDY_AUTO_RESET);
802       }
803     }
804   } else {
805     ProcessControlFrameHeader(control_frame_type_field);
806   }
807 
808   return original_len - len;
809 }
810 
ProcessControlFrameHeader(uint16 control_frame_type_field)811 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
812   DCHECK_EQ(SPDY_NO_ERROR, error_code_);
813   DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
814 
815   // Early detection of deprecated frames that we ignore.
816   if (protocol_version() <= SPDY3) {
817     if (control_frame_type_field == NOOP) {
818       current_frame_type_ = NOOP;
819       DVLOG(1) << "NOOP control frame found. Ignoring.";
820       CHANGE_STATE(SPDY_AUTO_RESET);
821       return;
822     }
823 
824     if (control_frame_type_field == CREDENTIAL) {
825       current_frame_type_ = CREDENTIAL;
826       DCHECK_EQ(SPDY3, protocol_version());
827       DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
828       CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
829       return;
830     }
831   }
832 
833   if (!SpdyConstants::IsValidFrameType(protocol_version(),
834                                        control_frame_type_field)) {
835     DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
836                   << " (protocol version: " << protocol_version() << ")";
837     set_error(SPDY_INVALID_CONTROL_FRAME);
838     return;
839   }
840 
841   current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
842                                                       control_frame_type_field);
843 
844   // Do some sanity checking on the control frame sizes and flags.
845   switch (current_frame_type_) {
846     case SYN_STREAM:
847       if (current_frame_length_ < GetSynStreamMinimumSize()) {
848         set_error(SPDY_INVALID_CONTROL_FRAME);
849       } else if (current_frame_flags_ &
850                  ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
851         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
852       }
853       break;
854     case SYN_REPLY:
855       if (current_frame_length_ < GetSynReplyMinimumSize()) {
856         set_error(SPDY_INVALID_CONTROL_FRAME);
857       } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
858         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
859       }
860       break;
861     case RST_STREAM:
862       // For SPDY versions < 4, the header has a fixed length.
863       // For SPDY version 4 and up, the RST_STREAM frame may include optional
864       // opaque data, so we only have a lower limit on the frame size.
865       if ((current_frame_length_ != GetRstStreamMinimumSize() &&
866            protocol_version() <= SPDY3) ||
867           (current_frame_length_ < GetRstStreamMinimumSize() &&
868            protocol_version() > SPDY3)) {
869         set_error(SPDY_INVALID_CONTROL_FRAME);
870       } else if (current_frame_flags_ != 0) {
871         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
872       }
873       break;
874     case SETTINGS:
875     {
876       // Make sure that we have an integral number of 8-byte key/value pairs,
877       // plus a 4-byte length field in SPDY3 and below.
878       size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
879       // Size of each key/value pair in bytes.
880       size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5);
881       if (current_frame_length_ < GetSettingsMinimumSize() ||
882           (current_frame_length_ - GetControlFrameHeaderSize())
883           % setting_size != values_prefix_size) {
884         DLOG(WARNING) << "Invalid length for SETTINGS frame: "
885                       << current_frame_length_;
886         set_error(SPDY_INVALID_CONTROL_FRAME);
887       } else if (protocol_version() <= SPDY3 &&
888                  current_frame_flags_ &
889                  ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
890         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
891       } else if (protocol_version() > SPDY3 &&
892                  current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
893         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
894       } else if (protocol_version() > SPDY3 &&
895                  current_frame_flags_ & SETTINGS_FLAG_ACK &&
896                  current_frame_length_ > GetSettingsMinimumSize()) {
897         set_error(SPDY_INVALID_CONTROL_FRAME);
898       }
899       break;
900     }
901     case PING:
902       if (current_frame_length_ != GetPingSize()) {
903         set_error(SPDY_INVALID_CONTROL_FRAME);
904       } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
905                  (current_frame_flags_ & ~PING_FLAG_ACK)) {
906         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
907       }
908       break;
909     case GOAWAY:
910       {
911         // For SPDY version < 4, there are only mandatory fields and the header
912         // has a fixed length. For SPDY version >= 4, optional opaque data may
913         // be appended to the GOAWAY frame, thus there is only a minimal length
914         // restriction.
915         if ((current_frame_length_ != GetGoAwayMinimumSize() &&
916              protocol_version() <= SPDY3) ||
917             (current_frame_length_ < GetGoAwayMinimumSize() &&
918              protocol_version() > SPDY3)) {
919           set_error(SPDY_INVALID_CONTROL_FRAME);
920         } else if (current_frame_flags_ != 0) {
921           set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
922         }
923         break;
924       }
925     case HEADERS:
926       {
927         size_t min_size = GetHeadersMinimumSize();
928         if (protocol_version() > SPDY3 &&
929             (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
930           min_size += 4;
931         }
932         if (current_frame_length_ < min_size) {
933           set_error(SPDY_INVALID_CONTROL_FRAME);
934         } else if (protocol_version() <= SPDY3 &&
935                    current_frame_flags_ & ~CONTROL_FLAG_FIN) {
936           set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
937         } else if (protocol_version() > SPDY3 &&
938                    current_frame_flags_ &
939                        ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
940                          HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
941                          HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
942           set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
943         }
944       }
945       break;
946     case WINDOW_UPDATE:
947       if (current_frame_length_ != GetWindowUpdateSize()) {
948         set_error(SPDY_INVALID_CONTROL_FRAME);
949       } else if (current_frame_flags_ != 0) {
950         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
951       }
952       break;
953     case BLOCKED:
954       if (current_frame_length_ != GetBlockedSize() ||
955           protocol_version() <= SPDY3) {
956         // TODO(mlavan): BLOCKED frames are no longer part of SPDY4.
957         set_error(SPDY_INVALID_CONTROL_FRAME);
958       } else if (current_frame_flags_ != 0) {
959         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
960       }
961       break;
962     case PUSH_PROMISE:
963       if (current_frame_length_ < GetPushPromiseMinimumSize()) {
964         set_error(SPDY_INVALID_CONTROL_FRAME);
965       } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
966         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
967       } else if (protocol_version() > SPDY3 &&
968                  current_frame_flags_ &
969                      ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
970                        HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
971         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
972       }
973       break;
974     case CONTINUATION:
975       if (current_frame_length_ < GetContinuationMinimumSize() ||
976           protocol_version() <= SPDY3) {
977         set_error(SPDY_INVALID_CONTROL_FRAME);
978       } else if (current_frame_flags_ &
979                  ~(HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PAD_LOW |
980                    HEADERS_FLAG_PAD_HIGH)) {
981         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
982       }
983       break;
984     case ALTSVC:
985       if (current_frame_length_ <= GetAltSvcMinimumSize()) {
986         set_error(SPDY_INVALID_CONTROL_FRAME);
987       } else if (current_frame_flags_ != 0) {
988         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
989       }
990       break;
991     case PRIORITY:
992       if (current_frame_length_ != GetPrioritySize() ||
993           protocol_version() <= SPDY3) {
994         set_error(SPDY_INVALID_CONTROL_FRAME);
995       } else if (current_frame_flags_ != 0) {
996         set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
997       }
998       break;
999     default:
1000       LOG(WARNING) << "Valid " << display_protocol_
1001                    << " control frame with unhandled type: "
1002                    << current_frame_type_;
1003       // This branch should be unreachable because of the frame type bounds
1004       // check above. However, we DLOG(FATAL) here in an effort to painfully
1005       // club the head of the developer who failed to keep this file in sync
1006       // with spdy_protocol.h.
1007       DLOG(FATAL);
1008       set_error(SPDY_INVALID_CONTROL_FRAME);
1009       break;
1010   }
1011 
1012   if (state_ == SPDY_ERROR) {
1013     return;
1014   }
1015 
1016   if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
1017     DLOG(WARNING) << "Received control frame with way too big of a payload: "
1018                   << current_frame_length_;
1019     set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1020     return;
1021   }
1022 
1023   if (current_frame_type_ == GOAWAY) {
1024     CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
1025     return;
1026   }
1027 
1028   if (current_frame_type_ == RST_STREAM) {
1029     CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
1030     return;
1031   }
1032 
1033   if (current_frame_type_ == ALTSVC) {
1034     CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1035     return;
1036   }
1037   // Determine the frame size without variable-length data.
1038   int32 frame_size_without_variable_data;
1039   switch (current_frame_type_) {
1040     case SYN_STREAM:
1041       syn_frame_processed_ = true;
1042       frame_size_without_variable_data = GetSynStreamMinimumSize();
1043       break;
1044     case SYN_REPLY:
1045       syn_frame_processed_ = true;
1046       frame_size_without_variable_data = GetSynReplyMinimumSize();
1047       break;
1048     case SETTINGS:
1049       frame_size_without_variable_data = GetSettingsMinimumSize();
1050       break;
1051     case HEADERS:
1052       frame_size_without_variable_data = GetHeadersMinimumSize();
1053       if (protocol_version() > SPDY3 &&
1054           current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1055         frame_size_without_variable_data +=
1056             kPriorityDependencyPayloadSize +
1057             kPriorityWeightPayloadSize;
1058       }
1059       break;
1060     case PUSH_PROMISE:
1061       frame_size_without_variable_data = GetPushPromiseMinimumSize();
1062       break;
1063     case CONTINUATION:
1064       frame_size_without_variable_data = GetContinuationMinimumSize();
1065       break;
1066     default:
1067       frame_size_without_variable_data = -1;
1068       break;
1069   }
1070 
1071   if ((frame_size_without_variable_data == -1) &&
1072       (current_frame_length_ > kControlFrameBufferSize)) {
1073     // We should already be in an error state. Double-check.
1074     DCHECK_EQ(SPDY_ERROR, state_);
1075     if (state_ != SPDY_ERROR) {
1076       LOG(DFATAL) << display_protocol_
1077                   << " control frame buffer too small for fixed-length frame.";
1078       set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1079     }
1080     return;
1081   }
1082 
1083   if (frame_size_without_variable_data > 0) {
1084     // We have a control frame with a header block. We need to parse the
1085     // remainder of the control frame's header before we can parse the header
1086     // block. The start of the header block varies with the control type.
1087     DCHECK_GE(frame_size_without_variable_data,
1088               static_cast<int32>(current_frame_buffer_length_));
1089     remaining_control_header_ = frame_size_without_variable_data -
1090         current_frame_buffer_length_;
1091 
1092     CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
1093     return;
1094   }
1095 
1096   CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
1097 }
1098 
UpdateCurrentFrameBuffer(const char ** data,size_t * len,size_t max_bytes)1099 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
1100                                             size_t max_bytes) {
1101   size_t bytes_to_read = std::min(*len, max_bytes);
1102   if (bytes_to_read > 0) {
1103     DCHECK_GE(kControlFrameBufferSize,
1104               current_frame_buffer_length_ + bytes_to_read);
1105     memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
1106            *data,
1107            bytes_to_read);
1108     current_frame_buffer_length_ += bytes_to_read;
1109     *data += bytes_to_read;
1110     *len -= bytes_to_read;
1111   }
1112   return bytes_to_read;
1113 }
1114 
GetSerializedLength(const SpdyMajorVersion spdy_version,const SpdyHeaderBlock * headers)1115 size_t SpdyFramer::GetSerializedLength(
1116     const SpdyMajorVersion spdy_version,
1117     const SpdyHeaderBlock* headers) {
1118   const size_t num_name_value_pairs_size
1119       = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
1120   const size_t length_of_name_size = num_name_value_pairs_size;
1121   const size_t length_of_value_size = num_name_value_pairs_size;
1122 
1123   size_t total_length = num_name_value_pairs_size;
1124   for (SpdyHeaderBlock::const_iterator it = headers->begin();
1125        it != headers->end();
1126        ++it) {
1127     // We add space for the length of the name and the length of the value as
1128     // well as the length of the name and the length of the value.
1129     total_length += length_of_name_size + it->first.size() +
1130                     length_of_value_size + it->second.size();
1131   }
1132   return total_length;
1133 }
1134 
WriteHeaderBlock(SpdyFrameBuilder * frame,const SpdyMajorVersion spdy_version,const SpdyHeaderBlock * headers)1135 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
1136                                   const SpdyMajorVersion spdy_version,
1137                                   const SpdyHeaderBlock* headers) {
1138   if (spdy_version < SPDY3) {
1139     frame->WriteUInt16(headers->size());  // Number of headers.
1140   } else {
1141     frame->WriteUInt32(headers->size());  // Number of headers.
1142   }
1143   SpdyHeaderBlock::const_iterator it;
1144   for (it = headers->begin(); it != headers->end(); ++it) {
1145     if (spdy_version < SPDY3) {
1146       frame->WriteString(it->first);
1147       frame->WriteString(it->second);
1148     } else {
1149       frame->WriteStringPiece32(it->first);
1150       frame->WriteStringPiece32(it->second);
1151     }
1152   }
1153 }
1154 
1155 // TODO(phajdan.jr): Clean up after we no longer need
1156 // to workaround http://crbug.com/139744.
1157 #if !defined(USE_SYSTEM_ZLIB)
1158 
1159 // These constants are used by zlib to differentiate between normal data and
1160 // cookie data. Cookie data is handled specially by zlib when compressing.
1161 enum ZDataClass {
1162   // kZStandardData is compressed normally, save that it will never match
1163   // against any other class of data in the window.
1164   kZStandardData = Z_CLASS_STANDARD,
1165   // kZCookieData is compressed in its own Huffman blocks and only matches in
1166   // its entirety and only against other kZCookieData blocks. Any matches must
1167   // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1168   // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1169   // prefix matches.
1170   kZCookieData = Z_CLASS_COOKIE,
1171   // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1172   // against the window.
1173   kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
1174 };
1175 
1176 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1177 // needed when switching between classes of data.
WriteZ(const base::StringPiece & data,ZDataClass clas,z_stream * out)1178 static void WriteZ(const base::StringPiece& data,
1179                    ZDataClass clas,
1180                    z_stream* out) {
1181   int rv;
1182 
1183   // If we are switching from standard to non-standard data then we need to end
1184   // the current Huffman context to avoid it leaking between them.
1185   if (out->clas == kZStandardData &&
1186       clas != kZStandardData) {
1187     out->avail_in = 0;
1188     rv = deflate(out, Z_PARTIAL_FLUSH);
1189     DCHECK_EQ(Z_OK, rv);
1190     DCHECK_EQ(0u, out->avail_in);
1191     DCHECK_LT(0u, out->avail_out);
1192   }
1193 
1194   out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1195   out->avail_in = data.size();
1196   out->clas = clas;
1197   if (clas == kZStandardData) {
1198     rv = deflate(out, Z_NO_FLUSH);
1199   } else {
1200     rv = deflate(out, Z_PARTIAL_FLUSH);
1201   }
1202   if (!data.empty()) {
1203     // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1204     DCHECK_EQ(Z_OK, rv);
1205   }
1206   DCHECK_EQ(0u, out->avail_in);
1207   DCHECK_LT(0u, out->avail_out);
1208 }
1209 
1210 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
WriteLengthZ(size_t n,unsigned length,ZDataClass clas,z_stream * out)1211 static void WriteLengthZ(size_t n,
1212                          unsigned length,
1213                          ZDataClass clas,
1214                          z_stream* out) {
1215   char buf[4];
1216   DCHECK_LE(length, sizeof(buf));
1217   for (unsigned i = 1; i <= length; i++) {
1218     buf[length - i] = n;
1219     n >>= 8;
1220   }
1221   WriteZ(base::StringPiece(buf, length), clas, out);
1222 }
1223 
1224 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1225 // manner that resists the length of the compressed data from compromising
1226 // cookie data.
WriteHeaderBlockToZ(const SpdyHeaderBlock * headers,z_stream * z) const1227 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1228                                      z_stream* z) const {
1229   unsigned length_length = 4;
1230   if (spdy_version_ < 3)
1231     length_length = 2;
1232 
1233   WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1234 
1235   std::map<std::string, std::string>::const_iterator it;
1236   for (it = headers->begin(); it != headers->end(); ++it) {
1237     WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1238     WriteZ(it->first, kZStandardData, z);
1239 
1240     if (it->first == "cookie") {
1241       // We require the cookie values (save for the last) to end with a
1242       // semicolon and (save for the first) to start with a space. This is
1243       // typically the format that we are given them in but we reserialize them
1244       // to be sure.
1245 
1246       std::vector<base::StringPiece> cookie_values;
1247       size_t cookie_length = 0;
1248       base::StringPiece cookie_data(it->second);
1249 
1250       for (;;) {
1251         while (!cookie_data.empty() &&
1252                (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1253           cookie_data.remove_prefix(1);
1254         }
1255         if (cookie_data.empty())
1256           break;
1257 
1258         size_t i;
1259         for (i = 0; i < cookie_data.size(); i++) {
1260           if (cookie_data[i] == ';')
1261             break;
1262         }
1263         if (i < cookie_data.size()) {
1264           cookie_values.push_back(cookie_data.substr(0, i));
1265           cookie_length += i + 2 /* semicolon and space */;
1266           cookie_data.remove_prefix(i + 1);
1267         } else {
1268           cookie_values.push_back(cookie_data);
1269           cookie_length += cookie_data.size();
1270           cookie_data.remove_prefix(i);
1271         }
1272       }
1273 
1274       WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1275       for (size_t i = 0; i < cookie_values.size(); i++) {
1276         std::string cookie;
1277         // Since zlib will only back-reference complete cookies, a cookie that
1278         // is currently last (and so doesn't have a trailing semicolon) won't
1279         // match if it's later in a non-final position. The same is true of
1280         // the first cookie.
1281         if (i == 0 && cookie_values.size() == 1) {
1282           cookie = cookie_values[i].as_string();
1283         } else if (i == 0) {
1284           cookie = cookie_values[i].as_string() + ";";
1285         } else if (i < cookie_values.size() - 1) {
1286           cookie = " " + cookie_values[i].as_string() + ";";
1287         } else {
1288           cookie = " " + cookie_values[i].as_string();
1289         }
1290         WriteZ(cookie, kZCookieData, z);
1291       }
1292     } else if (it->first == "accept" ||
1293                it->first == "accept-charset" ||
1294                it->first == "accept-encoding" ||
1295                it->first == "accept-language" ||
1296                it->first == "host" ||
1297                it->first == "version" ||
1298                it->first == "method" ||
1299                it->first == "scheme" ||
1300                it->first == ":host" ||
1301                it->first == ":version" ||
1302                it->first == ":method" ||
1303                it->first == ":scheme" ||
1304                it->first == "user-agent") {
1305       WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1306       WriteZ(it->second, kZStandardData, z);
1307     } else {
1308       // Non-whitelisted headers are Huffman compressed in their own block, but
1309       // don't match against the window.
1310       WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1311       WriteZ(it->second, kZHuffmanOnlyData, z);
1312     }
1313   }
1314 
1315   z->avail_in = 0;
1316   int rv = deflate(z, Z_SYNC_FLUSH);
1317   DCHECK_EQ(Z_OK, rv);
1318   z->clas = kZStandardData;
1319 }
1320 #endif  // !defined(USE_SYSTEM_ZLIB)
1321 
ProcessControlFrameBeforeHeaderBlock(const char * data,size_t len)1322 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1323                                                         size_t len) {
1324   DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1325   const size_t original_len = len;
1326 
1327   if (remaining_control_header_ > 0) {
1328     size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1329                                                  remaining_control_header_);
1330     remaining_control_header_ -= bytes_read;
1331     remaining_data_length_ -= bytes_read;
1332   }
1333 
1334   if (remaining_control_header_ == 0) {
1335     SpdyFrameReader reader(current_frame_buffer_.get(),
1336                            current_frame_buffer_length_);
1337     reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
1338 
1339     switch (current_frame_type_) {
1340       case SYN_STREAM:
1341         {
1342           DCHECK_GE(SPDY3, protocol_version());
1343           bool successful_read = true;
1344           successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1345           DCHECK(successful_read);
1346           if (current_frame_stream_id_ == 0) {
1347             set_error(SPDY_INVALID_CONTROL_FRAME);
1348             break;
1349           }
1350 
1351           SpdyStreamId associated_to_stream_id = kInvalidStream;
1352           successful_read = reader.ReadUInt31(&associated_to_stream_id);
1353           DCHECK(successful_read);
1354 
1355           SpdyPriority priority = 0;
1356           successful_read = reader.ReadUInt8(&priority);
1357           DCHECK(successful_read);
1358           if (protocol_version() <= SPDY2) {
1359             priority = priority >> 6;
1360           } else {
1361             priority = priority >> 5;
1362           }
1363 
1364          // Seek past unused byte; used to be credential slot in SPDY 3.
1365          reader.Seek(1);
1366 
1367           DCHECK(reader.IsDoneReading());
1368           if (debug_visitor_) {
1369             debug_visitor_->OnReceiveCompressedFrame(
1370                 current_frame_stream_id_,
1371                 current_frame_type_,
1372                 current_frame_length_);
1373           }
1374           visitor_->OnSynStream(
1375               current_frame_stream_id_,
1376               associated_to_stream_id,
1377               priority,
1378               (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1379               (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1380         }
1381         CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1382         break;
1383       case SETTINGS:
1384         if (protocol_version() > SPDY3 &&
1385             current_frame_flags_ & SETTINGS_FLAG_ACK) {
1386           visitor_->OnSettingsAck();
1387           CHANGE_STATE(SPDY_AUTO_RESET);
1388         } else {
1389           visitor_->OnSettings(current_frame_flags_ &
1390               SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1391           CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1392         }
1393         break;
1394       case SYN_REPLY:
1395       case HEADERS:
1396         // SYN_REPLY and HEADERS are the same, save for the visitor call.
1397         {
1398           if (protocol_version() > SPDY3) {
1399             DCHECK_EQ(HEADERS, current_frame_type_);
1400           }
1401           bool successful_read = true;
1402           if (protocol_version() <= SPDY3) {
1403             successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1404             DCHECK(successful_read);
1405           }
1406           if (current_frame_stream_id_ == 0) {
1407             set_error(SPDY_INVALID_CONTROL_FRAME);
1408             break;
1409           }
1410           if (protocol_version() <= SPDY2) {
1411             // SPDY 2 had two unused bytes here. Seek past them.
1412             reader.Seek(2);
1413           }
1414           if (protocol_version() > SPDY3 &&
1415              !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1416              current_frame_type_ == HEADERS) {
1417             expect_continuation_ = current_frame_stream_id_;
1418             end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1419           }
1420           const bool has_priority =
1421               (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1422           uint32 priority = 0;
1423           if (protocol_version() > SPDY3 && has_priority) {
1424             // TODO(jgraettinger): Process dependency rather than ignoring it.
1425             reader.Seek(kPriorityDependencyPayloadSize);
1426             uint8 weight = 0;
1427             successful_read = reader.ReadUInt8(&weight);
1428             if (successful_read) {
1429               priority = MapWeightToPriority(weight);
1430             }
1431           }
1432           DCHECK(reader.IsDoneReading());
1433           if (debug_visitor_) {
1434             // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1435             SpdyFrameType reported_type = current_frame_type_;
1436             if (protocol_version() > SPDY3 && has_priority) {
1437               reported_type = SYN_STREAM;
1438             }
1439             debug_visitor_->OnReceiveCompressedFrame(
1440                 current_frame_stream_id_,
1441                 reported_type,
1442                 current_frame_length_);
1443           }
1444           if (current_frame_type_ == SYN_REPLY) {
1445             visitor_->OnSynReply(
1446                 current_frame_stream_id_,
1447                 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1448           } else if (protocol_version() > SPDY3 &&
1449               current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1450             // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1451             // can be made independent of wire changes.
1452             visitor_->OnSynStream(
1453                 current_frame_stream_id_,
1454                 0,  // associated_to_stream_id
1455                 priority,
1456                 current_frame_flags_ & CONTROL_FLAG_FIN,
1457                 false);  // unidirectional
1458           } else {
1459             visitor_->OnHeaders(
1460                 current_frame_stream_id_,
1461                 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1462                 expect_continuation_ == 0);
1463           }
1464         }
1465         CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1466         break;
1467       case PUSH_PROMISE:
1468         {
1469           DCHECK_LT(SPDY3, protocol_version());
1470           if (current_frame_stream_id_ == 0) {
1471             set_error(SPDY_INVALID_CONTROL_FRAME);
1472             break;
1473           }
1474           SpdyStreamId promised_stream_id = kInvalidStream;
1475           bool successful_read = reader.ReadUInt31(&promised_stream_id);
1476           DCHECK(successful_read);
1477           DCHECK(reader.IsDoneReading());
1478           if (promised_stream_id == 0) {
1479             set_error(SPDY_INVALID_CONTROL_FRAME);
1480             break;
1481           }
1482           if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1483             expect_continuation_ = current_frame_stream_id_;
1484           }
1485           if (debug_visitor_) {
1486             debug_visitor_->OnReceiveCompressedFrame(
1487                 current_frame_stream_id_,
1488                 current_frame_type_,
1489                 current_frame_length_);
1490           }
1491           visitor_->OnPushPromise(current_frame_stream_id_,
1492                                   promised_stream_id,
1493                                   (current_frame_flags_ &
1494                                    PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1495         }
1496         CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1497         break;
1498       case CONTINUATION:
1499         {
1500           // Check to make sure the stream id of the current frame is
1501           // the same as that of the preceding frame.
1502           // If we're at this point we should already know that
1503           // expect_continuation_ != 0, so this doubles as a check
1504           // that current_frame_stream_id != 0.
1505           if (current_frame_stream_id_ != expect_continuation_) {
1506             set_error(SPDY_INVALID_CONTROL_FRAME);
1507             break;
1508           }
1509           if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1510             expect_continuation_ = 0;
1511           }
1512           if (debug_visitor_) {
1513             debug_visitor_->OnReceiveCompressedFrame(
1514                 current_frame_stream_id_,
1515                 current_frame_type_,
1516                 current_frame_length_);
1517           }
1518           visitor_->OnContinuation(current_frame_stream_id_,
1519                                    (current_frame_flags_ &
1520                                     HEADERS_FLAG_END_HEADERS) != 0);
1521         }
1522         CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1523         break;
1524       default:
1525         DCHECK(false);
1526     }
1527   }
1528   return original_len - len;
1529 }
1530 
1531 // Does not buffer the control payload. Instead, either passes directly to the
1532 // visitor or decompresses and then passes directly to the visitor, via
1533 // IncrementallyDeliverControlFrameHeaderData() or
1534 // IncrementallyDecompressControlFrameHeaderData() respectively.
ProcessControlFrameHeaderBlock(const char * data,size_t data_len,bool is_hpack_header_block)1535 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1536                                                   size_t data_len,
1537                                                   bool is_hpack_header_block) {
1538   DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1539 
1540   bool processed_successfully = true;
1541   if (current_frame_type_ != SYN_STREAM &&
1542       current_frame_type_ != SYN_REPLY &&
1543       current_frame_type_ != HEADERS &&
1544       current_frame_type_ != PUSH_PROMISE &&
1545       current_frame_type_ != CONTINUATION) {
1546     LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1547   }
1548   size_t process_bytes = std::min(
1549       data_len, remaining_data_length_ - remaining_padding_payload_length_);
1550   if (is_hpack_header_block) {
1551     if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1552             current_frame_stream_id_, data, process_bytes)) {
1553       // TODO(jgraettinger): Finer-grained HPACK error codes.
1554       set_error(SPDY_DECOMPRESS_FAILURE);
1555       processed_successfully = false;
1556     }
1557   } else if (process_bytes > 0) {
1558     if (enable_compression_ && protocol_version() <= SPDY3) {
1559       processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1560           current_frame_stream_id_, data, process_bytes);
1561     } else {
1562       processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1563           current_frame_stream_id_, data, process_bytes);
1564     }
1565   }
1566   remaining_data_length_ -= process_bytes;
1567 
1568   // Handle the case that there is no futher data in this frame.
1569   if (remaining_data_length_ == remaining_padding_payload_length_ &&
1570       processed_successfully) {
1571     if (expect_continuation_ == 0) {
1572       if (is_hpack_header_block) {
1573         if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1574                 current_frame_stream_id_)) {
1575           set_error(SPDY_DECOMPRESS_FAILURE);
1576           processed_successfully = false;
1577         } else {
1578           // TODO(jgraettinger): To be removed with migration to
1579           // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1580           // block, delivered via reentrant call to
1581           // ProcessControlFrameHeaderBlock().
1582           DeliverHpackBlockAsSpdy3Block();
1583           return process_bytes;
1584         }
1585       } else {
1586         // The complete header block has been delivered. We send a zero-length
1587         // OnControlFrameHeaderData() to indicate this.
1588         visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1589       }
1590     }
1591     if (processed_successfully) {
1592       CHANGE_STATE(SPDY_CONSUME_PADDING);
1593     }
1594   }
1595 
1596   // Handle error.
1597   if (!processed_successfully) {
1598     return data_len;
1599   }
1600 
1601   // Return amount processed.
1602   return process_bytes;
1603 }
1604 
ProcessSettingsFramePayload(const char * data,size_t data_len)1605 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1606                                                size_t data_len) {
1607   DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1608   DCHECK_EQ(SETTINGS, current_frame_type_);
1609   size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1610   size_t processed_bytes = 0;
1611 
1612   size_t setting_size = protocol_version() <= SPDY3 ? 8 : 5;
1613 
1614   // Loop over our incoming data.
1615   while (unprocessed_bytes > 0) {
1616     // Process up to one setting at a time.
1617     size_t processing = std::min(
1618         unprocessed_bytes,
1619         static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len));
1620 
1621     // Check if we have a complete setting in our input.
1622     if (processing == setting_size) {
1623       // Parse the setting directly out of the input without buffering.
1624       if (!ProcessSetting(data + processed_bytes)) {
1625         set_error(SPDY_INVALID_CONTROL_FRAME);
1626         return processed_bytes;
1627       }
1628     } else {
1629       // Continue updating settings_scratch_.setting_buf.
1630       memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1631              data + processed_bytes,
1632              processing);
1633       settings_scratch_.setting_buf_len += processing;
1634 
1635       // Check if we have a complete setting buffered.
1636       if (settings_scratch_.setting_buf_len == setting_size) {
1637         if (!ProcessSetting(settings_scratch_.setting_buf)) {
1638           set_error(SPDY_INVALID_CONTROL_FRAME);
1639           return processed_bytes;
1640         }
1641         // Reset settings_scratch_.setting_buf for our next setting.
1642         settings_scratch_.setting_buf_len = 0;
1643       }
1644     }
1645 
1646     // Iterate.
1647     unprocessed_bytes -= processing;
1648     processed_bytes += processing;
1649   }
1650 
1651   // Check if we're done handling this SETTINGS frame.
1652   remaining_data_length_ -= processed_bytes;
1653   if (remaining_data_length_ == 0) {
1654     visitor_->OnSettingsEnd();
1655     CHANGE_STATE(SPDY_AUTO_RESET);
1656   }
1657 
1658   return processed_bytes;
1659 }
1660 
DeliverHpackBlockAsSpdy3Block()1661 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1662   DCHECK_LT(SPDY3, protocol_version());
1663   DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1664 
1665   const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
1666   if (block.empty()) {
1667     // Special-case this to make tests happy.
1668     ProcessControlFrameHeaderBlock(NULL, 0, false);
1669     return;
1670   }
1671   SpdyFrameBuilder builder(
1672       GetSerializedLength(protocol_version(), &block),
1673       SPDY3);
1674 
1675   SerializeNameValueBlockWithoutCompression(&builder, block);
1676   scoped_ptr<SpdyFrame> frame(builder.take());
1677 
1678   // Preserve padding length, and reset it after the re-entrant call.
1679   size_t remaining_padding = remaining_padding_payload_length_;
1680 
1681   remaining_padding_payload_length_ = 0;
1682   remaining_data_length_ = frame->size();
1683 
1684   ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1685 
1686   remaining_padding_payload_length_ = remaining_padding;
1687   remaining_data_length_ = remaining_padding;
1688 }
1689 
ProcessSetting(const char * data)1690 bool SpdyFramer::ProcessSetting(const char* data) {
1691   int id_field;
1692   SpdySettingsIds id;
1693   uint8 flags = 0;
1694   uint32 value;
1695 
1696   // Extract fields.
1697   // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1698   if (protocol_version() <= SPDY3) {
1699     const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1700     SettingsFlagsAndId id_and_flags =
1701       SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
1702     id_field = id_and_flags.id();
1703     flags = id_and_flags.flags();
1704     value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1705   } else {
1706     id_field = *(reinterpret_cast<const uint8*>(data));
1707     value = ntohl(*(reinterpret_cast<const uint32*>(data + 1)));
1708   }
1709 
1710   // Validate id.
1711   if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
1712     DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1713     return false;
1714   }
1715   id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
1716 
1717   if (protocol_version() <= SPDY3) {
1718     // Detect duplicates.
1719     if (id <= settings_scratch_.last_setting_id) {
1720       DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1721                     << " in " << display_protocol_ << " SETTINGS frame "
1722                     << "(last setting id was "
1723                     << settings_scratch_.last_setting_id << ").";
1724       return false;
1725     }
1726     settings_scratch_.last_setting_id = id;
1727 
1728     // Validate flags.
1729     uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1730     if ((flags & ~(kFlagsMask)) != 0) {
1731       DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1732                     << flags;
1733       return false;
1734     }
1735   }
1736 
1737   // Validation succeeded. Pass on to visitor.
1738   visitor_->OnSetting(id, flags, value);
1739   return true;
1740 }
1741 
ProcessControlFramePayload(const char * data,size_t len)1742 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1743   size_t original_len = len;
1744   size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1745                                                remaining_data_length_);
1746   remaining_data_length_ -= bytes_read;
1747   if (remaining_data_length_ == 0) {
1748     SpdyFrameReader reader(current_frame_buffer_.get(),
1749                            current_frame_buffer_length_);
1750     reader.Seek(GetControlFrameHeaderSize());  // Skip frame header.
1751 
1752     // Use frame-specific handlers.
1753     switch (current_frame_type_) {
1754       case PING: {
1755           SpdyPingId id = 0;
1756           bool is_ack = protocol_version() > SPDY3 &&
1757               (current_frame_flags_ & PING_FLAG_ACK);
1758           bool successful_read = true;
1759           if (protocol_version() <= SPDY3) {
1760             uint32 id32 = 0;
1761             successful_read = reader.ReadUInt32(&id32);
1762             id = id32;
1763           } else {
1764             successful_read = reader.ReadUInt64(&id);
1765           }
1766           DCHECK(successful_read);
1767           DCHECK(reader.IsDoneReading());
1768           visitor_->OnPing(id, is_ack);
1769         }
1770         break;
1771       case WINDOW_UPDATE: {
1772           uint32 delta_window_size = 0;
1773           bool successful_read = true;
1774           if (protocol_version() <= SPDY3) {
1775             successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1776             DCHECK(successful_read);
1777           }
1778           successful_read = reader.ReadUInt32(&delta_window_size);
1779           DCHECK(successful_read);
1780           DCHECK(reader.IsDoneReading());
1781           visitor_->OnWindowUpdate(current_frame_stream_id_,
1782                                    delta_window_size);
1783         }
1784         break;
1785       case BLOCKED: {
1786           DCHECK_LT(SPDY3, protocol_version());
1787           DCHECK(reader.IsDoneReading());
1788           visitor_->OnBlocked(current_frame_stream_id_);
1789         }
1790         break;
1791       case PRIORITY: {
1792           DCHECK_LT(SPDY3, protocol_version());
1793           // TODO(hkhalil): Process PRIORITY frames rather than ignore them.
1794           reader.Seek(5);
1795           DCHECK(reader.IsDoneReading());
1796         }
1797         break;
1798       default:
1799         // Unreachable.
1800         LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1801     }
1802 
1803     CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1804   }
1805   return original_len - len;
1806 }
1807 
ProcessGoAwayFramePayload(const char * data,size_t len)1808 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1809   if (len == 0) {
1810     return 0;
1811   }
1812   // Clamp to the actual remaining payload.
1813   if (len > remaining_data_length_) {
1814     len = remaining_data_length_;
1815   }
1816   size_t original_len = len;
1817 
1818   // Check if we had already read enough bytes to parse the GOAWAY header.
1819   const size_t header_size = GetGoAwayMinimumSize();
1820   size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1821   bool already_parsed_header = (unread_header_bytes == 0);
1822   if (!already_parsed_header) {
1823     // Buffer the new GOAWAY header bytes we got.
1824     UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1825 
1826     // Do we have enough to parse the constant size GOAWAY header?
1827     if (current_frame_buffer_length_ == header_size) {
1828       // Parse out the last good stream id.
1829       SpdyFrameReader reader(current_frame_buffer_.get(),
1830                              current_frame_buffer_length_);
1831       reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
1832       bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1833       DCHECK(successful_read);
1834 
1835       // In SPDYv3 and up, frames also specify a status code - parse it out.
1836       SpdyGoAwayStatus status = GOAWAY_OK;
1837       if (protocol_version() >= SPDY3) {
1838         uint32 status_raw = GOAWAY_OK;
1839         successful_read = reader.ReadUInt32(&status_raw);
1840         DCHECK(successful_read);
1841         if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1842                                                status_raw)) {
1843           status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
1844                                                     status_raw);
1845         } else {
1846           DCHECK(false);
1847           // Throw an error for SPDY4+, keep liberal behavior
1848           // for earlier versions.
1849           if (protocol_version() > SPDY3) {
1850             DLOG(WARNING) << "Invalid GO_AWAY status " << status_raw;
1851             set_error(SPDY_INVALID_CONTROL_FRAME);
1852             return 0;
1853           }
1854         }
1855       }
1856       // Finished parsing the GOAWAY header, call frame handler.
1857       visitor_->OnGoAway(current_frame_stream_id_, status);
1858     }
1859   }
1860 
1861   // Handle remaining data as opaque.
1862   bool processed_successfully = true;
1863   if (len > 0) {
1864     processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1865   }
1866   remaining_data_length_ -= original_len;
1867   if (!processed_successfully) {
1868     set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1869   } else if (remaining_data_length_ == 0) {
1870     // Signal that there is not more opaque data.
1871     visitor_->OnGoAwayFrameData(NULL, 0);
1872     CHANGE_STATE(SPDY_AUTO_RESET);
1873   }
1874   return original_len;
1875 }
1876 
ProcessRstStreamFramePayload(const char * data,size_t len)1877 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1878   if (len == 0) {
1879     return 0;
1880   }
1881   // Clamp to the actual remaining payload.
1882   if (len > remaining_data_length_) {
1883     len = remaining_data_length_;
1884   }
1885   size_t original_len = len;
1886 
1887   // Check if we had already read enough bytes to parse the fixed-length portion
1888   // of the RST_STREAM frame.
1889   const size_t header_size = GetRstStreamMinimumSize();
1890   size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1891   bool already_parsed_header = (unread_header_bytes == 0);
1892   if (!already_parsed_header) {
1893     // Buffer the new RST_STREAM header bytes we got.
1894     UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1895 
1896     // Do we have enough to parse the constant size RST_STREAM header?
1897     if (current_frame_buffer_length_ == header_size) {
1898       // Parse out the last good stream id.
1899       SpdyFrameReader reader(current_frame_buffer_.get(),
1900                              current_frame_buffer_length_);
1901       reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
1902       if (protocol_version() <= SPDY3) {
1903         bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1904         DCHECK(successful_read);
1905       }
1906 
1907       SpdyRstStreamStatus status = RST_STREAM_INVALID;
1908       uint32 status_raw = status;
1909       bool successful_read = reader.ReadUInt32(&status_raw);
1910       DCHECK(successful_read);
1911       if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1912                                                 status_raw)) {
1913         status = static_cast<SpdyRstStreamStatus>(status_raw);
1914       } else {
1915         // Throw an error for SPDY4+, keep liberal behavior
1916         // for earlier versions.
1917         if (protocol_version() > SPDY3) {
1918           DLOG(WARNING) << "Invalid RST_STREAM status " << status_raw;
1919           set_error(SPDY_INVALID_CONTROL_FRAME);
1920           return 0;
1921         }
1922       }
1923       // Finished parsing the RST_STREAM header, call frame handler.
1924       visitor_->OnRstStream(current_frame_stream_id_, status);
1925     }
1926   }
1927 
1928   // Handle remaining data as opaque.
1929   bool processed_successfully = true;
1930   if (len > 0) {
1931     processed_successfully = visitor_->OnRstStreamFrameData(data, len);
1932   }
1933   remaining_data_length_ -= original_len;
1934   if (!processed_successfully) {
1935     set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
1936   } else if (remaining_data_length_ == 0) {
1937     // Signal that there is not more opaque data.
1938     visitor_->OnRstStreamFrameData(NULL, 0);
1939     CHANGE_STATE(SPDY_AUTO_RESET);
1940   }
1941   return original_len;
1942 }
1943 
ProcessAltSvcFramePayload(const char * data,size_t len)1944 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
1945   if (len == 0) {
1946     return 0;
1947   }
1948 
1949   // Clamp to the actual remaining payload.
1950   len = std::min(len, remaining_data_length_);
1951 
1952   size_t processed_bytes = 0;
1953   size_t processing = 0;
1954   size_t bytes_remaining;
1955   char* buffer;
1956   size_t* buffer_len;
1957 
1958   while (len > 0) {
1959     if (altsvc_scratch_.pid_len == 0) {
1960       // The size of the frame up to the PID_LEN field.
1961       size_t fixed_len_portion = GetAltSvcMinimumSize() - 1;
1962       bytes_remaining = fixed_len_portion - current_frame_buffer_length_;
1963       processing = std::min(len, bytes_remaining);
1964       // Buffer the new ALTSVC bytes we got.
1965       UpdateCurrentFrameBuffer(&data, &len, processing);
1966 
1967       // Do we have enough to parse the length of the protocol id?
1968       if (current_frame_buffer_length_ == fixed_len_portion) {
1969         // Parse out the max age, port, and pid_len.
1970         SpdyFrameReader reader(current_frame_buffer_.get(),
1971                                current_frame_buffer_length_);
1972         reader.Seek(GetControlFrameHeaderSize());  // Seek past frame header.
1973         bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age);
1974         reader.ReadUInt16(&altsvc_scratch_.port);
1975         reader.Seek(1);  // Reserved byte.
1976         successful_read = successful_read &&
1977                           reader.ReadUInt8(&altsvc_scratch_.pid_len);
1978         DCHECK(successful_read);
1979         // Sanity check length value.
1980         if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >=
1981             current_frame_length_) {
1982           set_error(SPDY_INVALID_CONTROL_FRAME);
1983           return 0;
1984         }
1985         altsvc_scratch_.protocol_id.reset(
1986             new char[size_t(altsvc_scratch_.pid_len)]);
1987       }
1988       processed_bytes += processing;
1989       continue;
1990     } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) {
1991       // Buffer protocol id field as in comes in.
1992       buffer = altsvc_scratch_.protocol_id.get();
1993       buffer_len = &altsvc_scratch_.pid_buf_len;
1994       bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len;
1995     } else if (altsvc_scratch_.host_len == 0) {
1996       // Parse out the host length.
1997       processing = 1;
1998       altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data);
1999       // Sanity check length value.
2000       if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len +
2001           altsvc_scratch_.host_len > current_frame_length_) {
2002         set_error(SPDY_INVALID_CONTROL_FRAME);
2003         return 0;
2004       }
2005       altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]);
2006       // Once we have host length, we can also determine the origin length
2007       // by process of elimination.
2008       altsvc_scratch_.origin_len = current_frame_length_ -
2009         GetAltSvcMinimumSize() -
2010         altsvc_scratch_.pid_len -
2011         altsvc_scratch_.host_len;
2012       if (altsvc_scratch_.origin_len > 0) {
2013         altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]);
2014       }
2015       data += processing;
2016       processed_bytes += processing;
2017       len -= processing;
2018       continue;
2019     } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) {
2020       // Buffer host field as it comes in.
2021       // TODO(mlavan): check formatting for host and origin
2022       buffer = altsvc_scratch_.host.get();
2023       buffer_len = &altsvc_scratch_.host_buf_len;
2024       bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len;
2025     } else {
2026       // Buffer (optional) origin field as it comes in.
2027       if (altsvc_scratch_.origin_len <= 0) {
2028         set_error(SPDY_INVALID_CONTROL_FRAME);
2029         return 0;
2030       }
2031       buffer = altsvc_scratch_.origin.get();
2032       buffer_len = &altsvc_scratch_.origin_buf_len;
2033       bytes_remaining = remaining_data_length_ -
2034         processed_bytes -
2035         altsvc_scratch_.origin_buf_len;
2036       if (len > bytes_remaining) {
2037         // This is our last field; there shouldn't be any more bytes.
2038         set_error(SPDY_INVALID_CONTROL_FRAME);
2039         return 0;
2040       }
2041     }
2042 
2043     // Copy data bytes into the appropriate field.
2044     processing = std::min(len, bytes_remaining);
2045     memcpy(buffer + *buffer_len,
2046            data,
2047            processing);
2048     *buffer_len += processing;
2049     data += processing;
2050     processed_bytes += processing;
2051     len -= processing;
2052   }
2053 
2054   remaining_data_length_ -= processed_bytes;
2055   if (remaining_data_length_ == 0) {
2056     visitor_->OnAltSvc(current_frame_stream_id_,
2057                        altsvc_scratch_.max_age,
2058                        altsvc_scratch_.port,
2059                        StringPiece(altsvc_scratch_.protocol_id.get(),
2060                                    altsvc_scratch_.pid_len),
2061                        StringPiece(altsvc_scratch_.host.get(),
2062                                    altsvc_scratch_.host_len),
2063                        StringPiece(altsvc_scratch_.origin.get(),
2064                                    altsvc_scratch_.origin_len));
2065     CHANGE_STATE(SPDY_AUTO_RESET);
2066   }
2067 
2068   return processed_bytes;
2069 }
2070 
ProcessFramePaddingLength(const char * data,size_t len)2071 size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
2072   DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_);
2073 
2074   size_t original_len = len;
2075   if (remaining_padding_length_fields_ == 0) {
2076     DCHECK_EQ(remaining_padding_payload_length_, 0u);
2077     bool pad_low = false;
2078     bool pad_high = false;
2079     if (current_frame_flags_ & DATA_FLAG_PAD_LOW) {
2080       pad_low = true;
2081       ++remaining_padding_length_fields_;
2082     }
2083     if (current_frame_flags_ & DATA_FLAG_PAD_HIGH) {
2084       pad_high = true;
2085       ++remaining_padding_length_fields_;
2086     }
2087     if ((pad_high && !pad_low) ||
2088         remaining_data_length_ < remaining_padding_length_fields_) {
2089       set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2090       return 0;
2091     }
2092   }
2093 
2094   // Parse the padding length.
2095   while (len != 0 && remaining_padding_length_fields_ != 0) {
2096     remaining_padding_payload_length_ =
2097         (remaining_padding_payload_length_ << 8) +
2098         *reinterpret_cast<const uint8*>(data);
2099     ++data;
2100     --len;
2101     --remaining_padding_length_fields_;
2102     --remaining_data_length_;
2103   }
2104 
2105   if (remaining_padding_length_fields_ == 0) {
2106     if (remaining_padding_payload_length_ > remaining_data_length_) {
2107       set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2108       return 0;
2109     }
2110     if (current_frame_type_ == DATA) {
2111       CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2112     } else {
2113       DCHECK(current_frame_type_ == HEADERS ||
2114              current_frame_type_ == PUSH_PROMISE ||
2115              current_frame_type_ == CONTINUATION ||
2116              current_frame_type_ == SYN_STREAM ||
2117              current_frame_type_ == SYN_REPLY)
2118           << current_frame_type_;
2119       CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
2120     }
2121   }
2122   return original_len - len;
2123 }
2124 
ProcessFramePadding(const char * data,size_t len)2125 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
2126   DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
2127 
2128   size_t original_len = len;
2129   if (remaining_padding_payload_length_ > 0) {
2130     DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
2131     size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2132     if (current_frame_type_ == DATA && amount_to_discard > 0) {
2133       // The visitor needs to know about padding so it can send window updates.
2134       // Communicate the padding to the visitor through a NULL data pointer,
2135       // with a nonzero size.
2136       visitor_->OnStreamFrameData(
2137           current_frame_stream_id_, NULL, amount_to_discard, false);
2138     }
2139     data += amount_to_discard;
2140     len -= amount_to_discard;
2141     remaining_padding_payload_length_ -= amount_to_discard;
2142     remaining_data_length_ -= amount_to_discard;
2143   }
2144 
2145   if (remaining_data_length_ == 0) {
2146     // If the FIN flag is set, or this ends a header block which set FIN,
2147     // inform the visitor of EOF via a 0-length data frame.
2148     if (expect_continuation_ == 0 &&
2149         ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2150          end_stream_when_done_)) {
2151       end_stream_when_done_ = false;
2152       visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
2153     }
2154     CHANGE_STATE(SPDY_AUTO_RESET);
2155   }
2156   return original_len - len;
2157 }
2158 
ProcessDataFramePayload(const char * data,size_t len)2159 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
2160   size_t original_len = len;
2161   if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
2162     size_t amount_to_forward = std::min(
2163         remaining_data_length_ - remaining_padding_payload_length_, len);
2164     if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
2165       // Only inform the visitor if there is data.
2166       if (amount_to_forward) {
2167         visitor_->OnStreamFrameData(
2168             current_frame_stream_id_, data, amount_to_forward, false);
2169       }
2170     }
2171     data += amount_to_forward;
2172     len -= amount_to_forward;
2173     remaining_data_length_ -= amount_to_forward;
2174   }
2175 
2176   if (remaining_data_length_ == remaining_padding_payload_length_) {
2177     CHANGE_STATE(SPDY_CONSUME_PADDING);
2178   }
2179   return original_len - len;
2180 }
2181 
ProcessIgnoredControlFramePayload(size_t len)2182 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2183                                                      size_t len) {
2184   size_t original_len = len;
2185   if (remaining_data_length_ > 0) {
2186     size_t amount_to_ignore = std::min(remaining_data_length_, len);
2187     len -= amount_to_ignore;
2188     remaining_data_length_ -= amount_to_ignore;
2189   }
2190 
2191   if (remaining_data_length_ == 0) {
2192     CHANGE_STATE(SPDY_AUTO_RESET);
2193   }
2194   return original_len - len;
2195 }
2196 
ParseHeaderBlockInBuffer(const char * header_data,size_t header_length,SpdyHeaderBlock * block) const2197 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
2198                                           size_t header_length,
2199                                           SpdyHeaderBlock* block) const {
2200   SpdyFrameReader reader(header_data, header_length);
2201 
2202   // Read number of headers.
2203   uint32 num_headers;
2204   if (protocol_version() <= SPDY2) {
2205     uint16 temp;
2206     if (!reader.ReadUInt16(&temp)) {
2207       DVLOG(1) << "Unable to read number of headers.";
2208       return 0;
2209     }
2210     num_headers = temp;
2211   } else {
2212     if (!reader.ReadUInt32(&num_headers)) {
2213       DVLOG(1) << "Unable to read number of headers.";
2214       return 0;
2215     }
2216   }
2217 
2218   // Read each header.
2219   for (uint32 index = 0; index < num_headers; ++index) {
2220     base::StringPiece temp;
2221 
2222     // Read header name.
2223     if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2224                             : !reader.ReadStringPiece32(&temp)) {
2225       DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2226                << num_headers << ").";
2227       return 0;
2228     }
2229     std::string name = temp.as_string();
2230 
2231     // Read header value.
2232     if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2233                             : !reader.ReadStringPiece32(&temp)) {
2234       DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2235                << num_headers << ").";
2236       return 0;
2237     }
2238     std::string value = temp.as_string();
2239 
2240     // Ensure no duplicates.
2241     if (block->find(name) != block->end()) {
2242       DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2243                << num_headers << ").";
2244       return 0;
2245     }
2246 
2247     // Store header.
2248     (*block)[name] = value;
2249   }
2250   return reader.GetBytesConsumed();
2251 }
2252 
SerializeData(const SpdyDataIR & data_ir) const2253 SpdySerializedFrame* SpdyFramer::SerializeData(
2254     const SpdyDataIR& data_ir) const {
2255   uint8 flags = DATA_FLAG_NONE;
2256   if (data_ir.fin()) {
2257     flags = DATA_FLAG_FIN;
2258   }
2259 
2260   if (protocol_version() > SPDY3) {
2261     int num_padding_fields = 0;
2262     if (data_ir.pad_low()) {
2263       flags |= DATA_FLAG_PAD_LOW;
2264       ++num_padding_fields;
2265     }
2266     if (data_ir.pad_high()) {
2267       flags |= DATA_FLAG_PAD_HIGH;
2268       ++num_padding_fields;
2269     }
2270 
2271     const size_t size_with_padding = num_padding_fields +
2272         data_ir.data().length() + data_ir.padding_payload_len() +
2273         GetDataFrameMinimumSize();
2274     SpdyFrameBuilder builder(size_with_padding, protocol_version());
2275     builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2276     if (data_ir.pad_high()) {
2277       builder.WriteUInt8(data_ir.padding_payload_len() >> 8);
2278     }
2279     if (data_ir.pad_low()) {
2280       builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2281     }
2282     builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2283     if (data_ir.padding_payload_len() > 0) {
2284       string padding = string(data_ir.padding_payload_len(), '0');
2285       builder.WriteBytes(padding.data(), padding.length());
2286     }
2287     DCHECK_EQ(size_with_padding, builder.length());
2288     return builder.take();
2289   } else {
2290     const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
2291     SpdyFrameBuilder builder(size, protocol_version());
2292     builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2293     builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2294     DCHECK_EQ(size, builder.length());
2295     return builder.take();
2296   }
2297 }
2298 
SerializeDataFrameHeaderWithPaddingLengthField(const SpdyDataIR & data_ir) const2299 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2300     const SpdyDataIR& data_ir) const {
2301   uint8 flags = DATA_FLAG_NONE;
2302   if (data_ir.fin()) {
2303     flags = DATA_FLAG_FIN;
2304   }
2305 
2306   size_t frame_size = GetDataFrameMinimumSize();
2307   size_t num_padding_fields = 0;
2308   if (protocol_version() > SPDY3) {
2309     if (data_ir.pad_low()) {
2310       flags |= DATA_FLAG_PAD_LOW;
2311       ++num_padding_fields;
2312     }
2313     if (data_ir.pad_high()) {
2314       flags |= DATA_FLAG_PAD_HIGH;
2315       ++num_padding_fields;
2316     }
2317     frame_size += num_padding_fields;
2318   }
2319 
2320   SpdyFrameBuilder builder(frame_size, protocol_version());
2321   builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2322   if (protocol_version() > SPDY3) {
2323     if (data_ir.pad_high()) {
2324       builder.WriteUInt8(data_ir.padding_payload_len() >> 8);
2325     }
2326     if (data_ir.pad_low()) {
2327       builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2328     }
2329     builder.OverwriteLength(*this,  num_padding_fields +
2330         data_ir.data().length() + data_ir.padding_payload_len());
2331   } else {
2332     builder.OverwriteLength(*this, data_ir.data().length());
2333   }
2334   DCHECK_EQ(frame_size, builder.length());
2335   return builder.take();
2336 }
2337 
SerializeSynStream(const SpdySynStreamIR & syn_stream)2338 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
2339     const SpdySynStreamIR& syn_stream) {
2340   uint8 flags = 0;
2341   if (syn_stream.fin()) {
2342     flags |= CONTROL_FLAG_FIN;
2343   }
2344   if (syn_stream.unidirectional()) {
2345     // TODO(hkhalil): invalid for HTTP2.
2346     flags |= CONTROL_FLAG_UNIDIRECTIONAL;
2347   }
2348   // In SPDY >= 4, SYN_STREAM frames are HEADERS frames, but for now
2349   // we never expect to have to overflow into a CONTINUATION frame.
2350   if (protocol_version() > SPDY3) {
2351     flags |= HEADERS_FLAG_PRIORITY;
2352     flags |= HEADERS_FLAG_END_HEADERS;
2353   }
2354 
2355   // Sanitize priority.
2356   uint8 priority = syn_stream.priority();
2357   if (priority > GetLowestPriority()) {
2358     DLOG(DFATAL) << "Priority out-of-bounds.";
2359     priority = GetLowestPriority();
2360   }
2361 
2362   // The size of this frame, including variable-length name-value block.
2363   size_t size = GetSynStreamMinimumSize();
2364 
2365   string hpack_encoding;
2366   if (protocol_version() > SPDY3) {
2367     if (enable_compression_) {
2368       GetHpackEncoder()->EncodeHeaderSet(
2369           syn_stream.name_value_block(), &hpack_encoding);
2370     } else {
2371       GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2372           syn_stream.name_value_block(), &hpack_encoding);
2373     }
2374     size += hpack_encoding.size();
2375   } else {
2376     size += GetSerializedLength(syn_stream.name_value_block());
2377   }
2378 
2379   SpdyFrameBuilder builder(size, protocol_version());
2380   if (protocol_version() <= SPDY3) {
2381     builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2382     builder.WriteUInt32(syn_stream.stream_id());
2383     builder.WriteUInt32(syn_stream.associated_to_stream_id());
2384     builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2385     builder.WriteUInt8(0);  // Unused byte where credential slot used to be.
2386   } else {
2387     builder.BeginNewFrame(*this,
2388                           HEADERS,
2389                           flags,
2390                           syn_stream.stream_id());
2391     // TODO(jgraettinger): Plumb priorities and stream dependencies.
2392     builder.WriteUInt32(0);  // Non-exclusive bit and root stream ID.
2393     builder.WriteUInt8(MapPriorityToWeight(priority));
2394   }
2395   DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2396   if (protocol_version() > SPDY3) {
2397     builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2398   } else {
2399     SerializeNameValueBlock(&builder, syn_stream);
2400   }
2401 
2402   if (debug_visitor_) {
2403     const size_t payload_len = protocol_version() > SPDY3 ?
2404         hpack_encoding.size() :
2405         GetSerializedLength(protocol_version(),
2406                             &(syn_stream.name_value_block()));
2407     // SPDY 4 reports this compression as a SYN_STREAM compression.
2408     debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
2409                                           SYN_STREAM,
2410                                           payload_len,
2411                                           builder.length());
2412   }
2413 
2414   return builder.take();
2415 }
2416 
SerializeSynReply(const SpdySynReplyIR & syn_reply)2417 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
2418     const SpdySynReplyIR& syn_reply) {
2419   uint8 flags = 0;
2420   if (syn_reply.fin()) {
2421     flags |= CONTROL_FLAG_FIN;
2422   }
2423   // In SPDY >= 4, SYN_REPLY frames are HEADERS frames, but for now
2424   // we never expect to have to overflow into a CONTINUATION frame.
2425   if (protocol_version() > SPDY3) {
2426     flags |= HEADERS_FLAG_END_HEADERS;
2427   }
2428 
2429   // The size of this frame, including variable-length name-value block.
2430   size_t size = GetSynReplyMinimumSize();
2431 
2432   string hpack_encoding;
2433   if (protocol_version() > SPDY3) {
2434     if (enable_compression_) {
2435       GetHpackEncoder()->EncodeHeaderSet(
2436           syn_reply.name_value_block(), &hpack_encoding);
2437     } else {
2438       GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2439           syn_reply.name_value_block(), &hpack_encoding);
2440     }
2441     size += hpack_encoding.size();
2442   } else {
2443     size += GetSerializedLength(syn_reply.name_value_block());
2444   }
2445 
2446   SpdyFrameBuilder builder(size, protocol_version());
2447   if (protocol_version() <= SPDY3) {
2448     builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
2449     builder.WriteUInt32(syn_reply.stream_id());
2450   } else {
2451     builder.BeginNewFrame(*this,
2452                           HEADERS,
2453                           flags,
2454                           syn_reply.stream_id());
2455   }
2456   if (protocol_version() < SPDY3) {
2457     builder.WriteUInt16(0);  // Unused.
2458   }
2459   DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2460   if (protocol_version() > SPDY3) {
2461     builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2462   } else {
2463     SerializeNameValueBlock(&builder, syn_reply);
2464   }
2465 
2466   if (debug_visitor_) {
2467     const size_t payload_len = protocol_version() > SPDY3 ?
2468         hpack_encoding.size() :
2469         GetSerializedLength(protocol_version(),
2470                             &(syn_reply.name_value_block()));
2471     debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
2472                                           SYN_REPLY,
2473                                           payload_len,
2474                                           builder.length());
2475   }
2476 
2477   return builder.take();
2478 }
2479 
SerializeRstStream(const SpdyRstStreamIR & rst_stream) const2480 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
2481     const SpdyRstStreamIR& rst_stream) const {
2482   // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2483   // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2484   // which doesn't currently include RST_STREAM payloads. GFE flags have been
2485   // commented but left in place to simplify future patching.
2486   // Compute the output buffer size, taking opaque data into account.
2487   uint16 expected_length = GetRstStreamMinimumSize();
2488   if (protocol_version() > SPDY3) {
2489     expected_length += rst_stream.description().size();
2490   }
2491   SpdyFrameBuilder builder(expected_length, protocol_version());
2492 
2493   // Serialize the RST_STREAM frame.
2494   if (protocol_version() <= SPDY3) {
2495     builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
2496     builder.WriteUInt32(rst_stream.stream_id());
2497   } else {
2498     builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
2499   }
2500 
2501   builder.WriteUInt32(rst_stream.status());
2502 
2503   // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2504   if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
2505     builder.WriteBytes(rst_stream.description().data(),
2506                        rst_stream.description().size());
2507   }
2508 
2509   DCHECK_EQ(expected_length, builder.length());
2510   return builder.take();
2511 }
2512 
SerializeSettings(const SpdySettingsIR & settings) const2513 SpdySerializedFrame* SpdyFramer::SerializeSettings(
2514     const SpdySettingsIR& settings) const {
2515   uint8 flags = 0;
2516 
2517   if (protocol_version() <= SPDY3) {
2518     if (settings.clear_settings()) {
2519       flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2520     }
2521   } else {
2522     if (settings.is_ack()) {
2523       flags |= SETTINGS_FLAG_ACK;
2524     }
2525   }
2526   const SpdySettingsIR::ValueMap* values = &(settings.values());
2527 
2528   size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5);
2529   // Size, in bytes, of this SETTINGS frame.
2530   const size_t size = GetSettingsMinimumSize() +
2531                       (values->size() * setting_size);
2532   SpdyFrameBuilder builder(size, protocol_version());
2533   if (protocol_version() <= SPDY3) {
2534     builder.WriteControlFrameHeader(*this, SETTINGS, flags);
2535   } else {
2536     builder.BeginNewFrame(*this, SETTINGS, flags, 0);
2537   }
2538 
2539   // If this is an ACK, payload should be empty.
2540   if (protocol_version() > SPDY3 && settings.is_ack()) {
2541     return builder.take();
2542   }
2543 
2544   if (protocol_version() <= SPDY3) {
2545     builder.WriteUInt32(values->size());
2546   }
2547   DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2548   for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
2549        it != values->end();
2550        ++it) {
2551     if (protocol_version() <= SPDY3) {
2552       uint8 setting_flags = 0;
2553       if (it->second.persist_value) {
2554         setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2555       }
2556       if (it->second.persisted) {
2557         setting_flags |= SETTINGS_FLAG_PERSISTED;
2558       }
2559       SettingsFlagsAndId flags_and_id(
2560           setting_flags,
2561           SpdyConstants::SerializeSettingId(protocol_version(), it->first));
2562       uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2563       builder.WriteBytes(&id_and_flags_wire, 4);
2564     } else {
2565       builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(),
2566                                                            it->first));
2567     }
2568     builder.WriteUInt32(it->second.value);
2569   }
2570   DCHECK_EQ(size, builder.length());
2571   return builder.take();
2572 }
2573 
SerializePing(const SpdyPingIR & ping) const2574 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
2575   SpdyFrameBuilder builder(GetPingSize(), protocol_version());
2576   if (protocol_version() <= SPDY3) {
2577     builder.WriteControlFrameHeader(*this, PING, kNoFlags);
2578     builder.WriteUInt32(static_cast<uint32>(ping.id()));
2579   } else {
2580     uint8 flags = 0;
2581     if (ping.is_ack()) {
2582       flags |= PING_FLAG_ACK;
2583     }
2584     builder.BeginNewFrame(*this, PING, flags, 0);
2585     builder.WriteUInt64(ping.id());
2586   }
2587   DCHECK_EQ(GetPingSize(), builder.length());
2588   return builder.take();
2589 }
2590 
SerializeGoAway(const SpdyGoAwayIR & goaway) const2591 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
2592     const SpdyGoAwayIR& goaway) const {
2593 
2594   // Compute the output buffer size, take opaque data into account.
2595   uint16 expected_length = GetGoAwayMinimumSize();
2596   if (protocol_version() > SPDY3) {
2597     expected_length += goaway.description().size();
2598   }
2599   SpdyFrameBuilder builder(expected_length, protocol_version());
2600 
2601   // Serialize the GOAWAY frame.
2602   if (protocol_version() <= SPDY3) {
2603     builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
2604   } else {
2605     builder.BeginNewFrame(*this, GOAWAY, 0, 0);
2606   }
2607 
2608   // GOAWAY frames specify the last good stream id for all SPDY versions.
2609   builder.WriteUInt32(goaway.last_good_stream_id());
2610 
2611   // In SPDY3 and up, GOAWAY frames also specify the error status code.
2612   if (protocol_version() >= SPDY3) {
2613     // TODO(jgraettinger): Merge back to server-side.
2614     builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2615                                                              goaway.status()));
2616   }
2617 
2618   // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2619   if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
2620     builder.WriteBytes(goaway.description().data(),
2621                        goaway.description().size());
2622   }
2623 
2624   DCHECK_EQ(expected_length, builder.length());
2625   return builder.take();
2626 }
2627 
SerializeHeaders(const SpdyHeadersIR & headers)2628 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2629     const SpdyHeadersIR& headers) {
2630   uint8 flags = 0;
2631   if (headers.fin()) {
2632     flags |= CONTROL_FLAG_FIN;
2633   }
2634   if (protocol_version() > SPDY3) {
2635     // This will get overwritten if we overflow into a CONTINUATION frame.
2636     flags |= HEADERS_FLAG_END_HEADERS;
2637     if (headers.has_priority()) {
2638       flags |= HEADERS_FLAG_PRIORITY;
2639     }
2640   }
2641 
2642   // The size of this frame, including variable-length name-value block.
2643   size_t size = GetHeadersMinimumSize();
2644 
2645   uint32 priority = headers.priority();
2646   if (headers.has_priority()) {
2647     if (priority > GetLowestPriority()) {
2648       DLOG(DFATAL) << "Priority out-of-bounds.";
2649       priority = GetLowestPriority();
2650     }
2651     size += 4;
2652   }
2653 
2654   string hpack_encoding;
2655   if (protocol_version() > SPDY3) {
2656     if (enable_compression_) {
2657       GetHpackEncoder()->EncodeHeaderSet(
2658           headers.name_value_block(), &hpack_encoding);
2659     } else {
2660       GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2661           headers.name_value_block(), &hpack_encoding);
2662     }
2663     size += hpack_encoding.size();
2664     if (size > GetControlFrameBufferMaxSize()) {
2665       size += GetNumberRequiredContinuationFrames(size) *
2666               GetContinuationMinimumSize();
2667       flags &= ~HEADERS_FLAG_END_HEADERS;
2668     }
2669   } else {
2670     size += GetSerializedLength(headers.name_value_block());
2671   }
2672 
2673   SpdyFrameBuilder builder(size, protocol_version());
2674   if (protocol_version() <= SPDY3) {
2675     builder.WriteControlFrameHeader(*this, HEADERS, flags);
2676     builder.WriteUInt32(headers.stream_id());
2677   } else {
2678     builder.BeginNewFrame(*this,
2679                           HEADERS,
2680                           flags,
2681                           headers.stream_id());
2682     if (headers.has_priority()) {
2683       // TODO(jgraettinger): Plumb priorities and stream dependencies.
2684       builder.WriteUInt32(0);  // Non-exclusive bit and root stream ID.
2685       builder.WriteUInt8(MapPriorityToWeight(priority));
2686     }
2687   }
2688   if (protocol_version() <= SPDY2) {
2689     builder.WriteUInt16(0);  // Unused.
2690   }
2691   DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2692 
2693   if (protocol_version() > SPDY3) {
2694     WritePayloadWithContinuation(&builder,
2695                                  hpack_encoding,
2696                                  headers.stream_id(),
2697                                  HEADERS);
2698   } else {
2699     SerializeNameValueBlock(&builder, headers);
2700   }
2701 
2702   if (debug_visitor_) {
2703     const size_t payload_len = protocol_version() > SPDY3 ?
2704         hpack_encoding.size() :
2705         GetSerializedLength(protocol_version(),
2706                             &(headers.name_value_block()));
2707     debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2708                                           HEADERS,
2709                                           payload_len,
2710                                           builder.length());
2711   }
2712 
2713   return builder.take();
2714 }
2715 
SerializeWindowUpdate(const SpdyWindowUpdateIR & window_update) const2716 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2717     const SpdyWindowUpdateIR& window_update) const {
2718   SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
2719   if (protocol_version() <= SPDY3) {
2720     builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2721     builder.WriteUInt32(window_update.stream_id());
2722   } else {
2723     builder.BeginNewFrame(*this,
2724                           WINDOW_UPDATE,
2725                           kNoFlags,
2726                           window_update.stream_id());
2727   }
2728   builder.WriteUInt32(window_update.delta());
2729   DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2730   return builder.take();
2731 }
2732 
SerializeBlocked(const SpdyBlockedIR & blocked) const2733 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
2734   DCHECK_LT(SPDY3, protocol_version());
2735   SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
2736   builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
2737   return builder.take();
2738 }
2739 
SerializePushPromise(const SpdyPushPromiseIR & push_promise)2740 SpdyFrame* SpdyFramer::SerializePushPromise(
2741     const SpdyPushPromiseIR& push_promise) {
2742   DCHECK_LT(SPDY3, protocol_version());
2743   uint8 flags = 0;
2744   // This will get overwritten if we overflow into a CONTINUATION frame.
2745   flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2746   // The size of this frame, including variable-length name-value block.
2747   size_t size = GetPushPromiseMinimumSize();
2748 
2749   string hpack_encoding;
2750   if (protocol_version() > SPDY3) {
2751     if (enable_compression_) {
2752       GetHpackEncoder()->EncodeHeaderSet(
2753           push_promise.name_value_block(), &hpack_encoding);
2754     } else {
2755       GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2756           push_promise.name_value_block(), &hpack_encoding);
2757     }
2758     size += hpack_encoding.size();
2759     if (size > GetControlFrameBufferMaxSize()) {
2760       size += GetNumberRequiredContinuationFrames(size) *
2761               GetContinuationMinimumSize();
2762       flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2763     }
2764   } else {
2765     size += GetSerializedLength(push_promise.name_value_block());
2766   }
2767 
2768   SpdyFrameBuilder builder(size, protocol_version());
2769   builder.BeginNewFrame(*this,
2770                         PUSH_PROMISE,
2771                         flags,
2772                         push_promise.stream_id());
2773   builder.WriteUInt32(push_promise.promised_stream_id());
2774   DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2775 
2776   if (protocol_version() > SPDY3) {
2777     WritePayloadWithContinuation(&builder,
2778                                  hpack_encoding,
2779                                  push_promise.stream_id(),
2780                                  PUSH_PROMISE);
2781   } else {
2782     SerializeNameValueBlock(&builder, push_promise);
2783   }
2784 
2785   if (debug_visitor_) {
2786     const size_t payload_len = protocol_version() > SPDY3 ?
2787         hpack_encoding.size() :
2788         GetSerializedLength(protocol_version(),
2789                             &(push_promise.name_value_block()));
2790     debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2791         PUSH_PROMISE, payload_len, builder.length());
2792   }
2793 
2794   return builder.take();
2795 }
2796 
2797 // TODO(jgraettinger): This implementation is incorrect. The continuation
2798 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2799 // new one. Figure out whether it makes sense to keep SerializeContinuation().
SerializeContinuation(const SpdyContinuationIR & continuation)2800 SpdyFrame* SpdyFramer::SerializeContinuation(
2801     const SpdyContinuationIR& continuation) {
2802   CHECK_LT(SPDY3, protocol_version());
2803   uint8 flags = 0;
2804   if (continuation.end_headers()) {
2805     flags |= HEADERS_FLAG_END_HEADERS;
2806   }
2807 
2808   // The size of this frame, including variable-length name-value block.
2809   size_t size = GetContinuationMinimumSize();
2810   string hpack_encoding;
2811   if (enable_compression_) {
2812     GetHpackEncoder()->EncodeHeaderSet(
2813         continuation.name_value_block(), &hpack_encoding);
2814   } else {
2815     GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2816         continuation.name_value_block(), &hpack_encoding);
2817   }
2818   size += hpack_encoding.size();
2819 
2820   SpdyFrameBuilder builder(size, protocol_version());
2821   builder.BeginNewFrame(*this, CONTINUATION, flags,
2822       continuation.stream_id());
2823   DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2824 
2825   builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2826 
2827   if (debug_visitor_) {
2828     const size_t payload_len = hpack_encoding.size();
2829     debug_visitor_->OnSendCompressedFrame(continuation.stream_id(),
2830         CONTINUATION, payload_len, builder.length());
2831   }
2832 
2833   return builder.take();
2834 }
2835 
SerializeAltSvc(const SpdyAltSvcIR & altsvc)2836 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) {
2837   DCHECK_LT(SPDY3, protocol_version());
2838   size_t size = GetAltSvcMinimumSize();
2839   size += altsvc.protocol_id().length();
2840   size += altsvc.host().length();
2841   size += altsvc.origin().length();
2842 
2843   SpdyFrameBuilder builder(size, protocol_version());
2844   builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
2845 
2846   builder.WriteUInt32(altsvc.max_age());
2847   builder.WriteUInt16(altsvc.port());
2848   builder.WriteUInt8(0);  // Reserved.
2849   builder.WriteUInt8(altsvc.protocol_id().length());
2850   builder.WriteBytes(altsvc.protocol_id().data(),
2851                      altsvc.protocol_id().length());
2852   builder.WriteUInt8(altsvc.host().length());
2853   builder.WriteBytes(altsvc.host().data(), altsvc.host().length());
2854   builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
2855   DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2856   return builder.take();
2857 }
2858 
2859 namespace {
2860 
2861 class FrameSerializationVisitor : public SpdyFrameVisitor {
2862  public:
FrameSerializationVisitor(SpdyFramer * framer)2863   explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
~FrameSerializationVisitor()2864   virtual ~FrameSerializationVisitor() {}
2865 
ReleaseSerializedFrame()2866   SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2867 
VisitData(const SpdyDataIR & data)2868   virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2869     frame_.reset(framer_->SerializeData(data));
2870   }
VisitSynStream(const SpdySynStreamIR & syn_stream)2871   virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2872     frame_.reset(framer_->SerializeSynStream(syn_stream));
2873   }
VisitSynReply(const SpdySynReplyIR & syn_reply)2874   virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2875     frame_.reset(framer_->SerializeSynReply(syn_reply));
2876   }
VisitRstStream(const SpdyRstStreamIR & rst_stream)2877   virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2878     frame_.reset(framer_->SerializeRstStream(rst_stream));
2879   }
VisitSettings(const SpdySettingsIR & settings)2880   virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2881     frame_.reset(framer_->SerializeSettings(settings));
2882   }
VisitPing(const SpdyPingIR & ping)2883   virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2884     frame_.reset(framer_->SerializePing(ping));
2885   }
VisitGoAway(const SpdyGoAwayIR & goaway)2886   virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2887     frame_.reset(framer_->SerializeGoAway(goaway));
2888   }
VisitHeaders(const SpdyHeadersIR & headers)2889   virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2890     frame_.reset(framer_->SerializeHeaders(headers));
2891   }
VisitWindowUpdate(const SpdyWindowUpdateIR & window_update)2892   virtual void VisitWindowUpdate(
2893       const SpdyWindowUpdateIR& window_update) OVERRIDE {
2894     frame_.reset(framer_->SerializeWindowUpdate(window_update));
2895   }
VisitBlocked(const SpdyBlockedIR & blocked)2896   virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2897     frame_.reset(framer_->SerializeBlocked(blocked));
2898   }
VisitPushPromise(const SpdyPushPromiseIR & push_promise)2899   virtual void VisitPushPromise(
2900       const SpdyPushPromiseIR& push_promise) OVERRIDE {
2901     frame_.reset(framer_->SerializePushPromise(push_promise));
2902   }
VisitContinuation(const SpdyContinuationIR & continuation)2903   virtual void VisitContinuation(
2904       const SpdyContinuationIR& continuation) OVERRIDE {
2905     frame_.reset(framer_->SerializeContinuation(continuation));
2906   }
VisitAltSvc(const SpdyAltSvcIR & altsvc)2907   virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) OVERRIDE {
2908     frame_.reset(framer_->SerializeAltSvc(altsvc));
2909   }
2910 
2911  private:
2912   SpdyFramer* framer_;
2913   scoped_ptr<SpdySerializedFrame> frame_;
2914 };
2915 
2916 }  // namespace
2917 
SerializeFrame(const SpdyFrameIR & frame)2918 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2919   FrameSerializationVisitor visitor(this);
2920   frame.Visit(&visitor);
2921   return visitor.ReleaseSerializedFrame();
2922 }
2923 
GetSerializedLength(const SpdyHeaderBlock & headers)2924 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2925   CHECK_GE(SPDY3, protocol_version());
2926   const size_t uncompressed_length =
2927     GetSerializedLength(protocol_version(), &headers);
2928   if (!enable_compression_) {
2929     return uncompressed_length;
2930   }
2931   z_stream* compressor = GetHeaderCompressor();
2932   // Since we'll be performing lots of flushes when compressing the data,
2933   // zlib's lower bounds may be insufficient.
2934   return 2 * deflateBound(compressor, uncompressed_length);
2935 }
2936 
GetNumberRequiredContinuationFrames(size_t size)2937 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2938   const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize();
2939   DCHECK_GT(protocol_version(), SPDY3);
2940   DCHECK_GT(size, kMaxControlFrameSize);
2941   size_t overflow = size - kMaxControlFrameSize;
2942   return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1;
2943 }
2944 
WritePayloadWithContinuation(SpdyFrameBuilder * builder,const string & hpack_encoding,SpdyStreamId stream_id,SpdyFrameType type)2945 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2946                                               const string& hpack_encoding,
2947                                               SpdyStreamId stream_id,
2948                                               SpdyFrameType type) {
2949   const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize();
2950 
2951     // In addition to the prefix, fixed_field_size includes the size of
2952     // any fields that come before the variable-length name/value block.
2953     size_t fixed_field_size = 0;
2954     uint8 end_flag = 0;
2955     uint8 flags = 0;
2956     if (type == HEADERS) {
2957       fixed_field_size = GetHeadersMinimumSize();
2958       end_flag = HEADERS_FLAG_END_HEADERS;
2959     } else if (type == PUSH_PROMISE) {
2960       fixed_field_size = GetPushPromiseMinimumSize();
2961       end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2962     } else {
2963       DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2964                   << FrameTypeToString(type);
2965     }
2966 
2967     // Write as much of the payload as possible into the initial frame.
2968     size_t bytes_remaining = hpack_encoding.size() -
2969         std::min(hpack_encoding.size(),
2970                  kMaxControlFrameSize - fixed_field_size);
2971     builder->WriteBytes(&hpack_encoding[0],
2972                         hpack_encoding.size() - bytes_remaining);
2973 
2974     if (bytes_remaining > 0) {
2975       builder->OverwriteLength(*this,
2976           kMaxControlFrameSize - GetControlFrameHeaderSize());
2977     }
2978 
2979     // Tack on CONTINUATION frames for the overflow.
2980     while (bytes_remaining > 0) {
2981       size_t bytes_to_write = std::min(bytes_remaining,
2982                                        kMaxControlFrameSize -
2983                                        GetContinuationMinimumSize());
2984       // Write CONTINUATION frame prefix.
2985       if (bytes_remaining == bytes_to_write) {
2986         flags |= end_flag;
2987       }
2988       builder->BeginNewFrame(*this,
2989                              CONTINUATION,
2990                              flags,
2991                              stream_id);
2992       // Write payload fragment.
2993       builder->WriteBytes(&hpack_encoding[hpack_encoding.size() -
2994                                           bytes_remaining],
2995                           bytes_to_write);
2996       bytes_remaining -= bytes_to_write;
2997     }
2998 }
2999 
3000 // The following compression setting are based on Brian Olson's analysis. See
3001 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
3002 // for more details.
3003 #if defined(USE_SYSTEM_ZLIB)
3004 // System zlib is not expected to have workaround for http://crbug.com/139744,
3005 // so disable compression in that case.
3006 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
3007 static const int kCompressorLevel = 0;
3008 #else  // !defined(USE_SYSTEM_ZLIB)
3009 static const int kCompressorLevel = 9;
3010 #endif  // !defined(USE_SYSTEM_ZLIB)
3011 static const int kCompressorWindowSizeInBits = 11;
3012 static const int kCompressorMemLevel = 1;
3013 
GetHeaderCompressor()3014 z_stream* SpdyFramer::GetHeaderCompressor() {
3015   if (header_compressor_.get())
3016     return header_compressor_.get();  // Already initialized.
3017 
3018   header_compressor_.reset(new z_stream);
3019   memset(header_compressor_.get(), 0, sizeof(z_stream));
3020 
3021   int success = deflateInit2(header_compressor_.get(),
3022                              kCompressorLevel,
3023                              Z_DEFLATED,
3024                              kCompressorWindowSizeInBits,
3025                              kCompressorMemLevel,
3026                              Z_DEFAULT_STRATEGY);
3027   if (success == Z_OK) {
3028     const char* dictionary = (protocol_version() <= SPDY2) ?
3029         kV2Dictionary : kV3Dictionary;
3030     const int dictionary_size = (protocol_version() <= SPDY2) ?
3031         kV2DictionarySize : kV3DictionarySize;
3032     success = deflateSetDictionary(header_compressor_.get(),
3033                                    reinterpret_cast<const Bytef*>(dictionary),
3034                                    dictionary_size);
3035   }
3036   if (success != Z_OK) {
3037     LOG(WARNING) << "deflateSetDictionary failure: " << success;
3038     header_compressor_.reset(NULL);
3039     return NULL;
3040   }
3041   return header_compressor_.get();
3042 }
3043 
GetHeaderDecompressor()3044 z_stream* SpdyFramer::GetHeaderDecompressor() {
3045   if (header_decompressor_.get())
3046     return header_decompressor_.get();  // Already initialized.
3047 
3048   header_decompressor_.reset(new z_stream);
3049   memset(header_decompressor_.get(), 0, sizeof(z_stream));
3050 
3051   int success = inflateInit(header_decompressor_.get());
3052   if (success != Z_OK) {
3053     LOG(WARNING) << "inflateInit failure: " << success;
3054     header_decompressor_.reset(NULL);
3055     return NULL;
3056   }
3057   return header_decompressor_.get();
3058 }
3059 
GetHpackEncoder()3060 HpackEncoder* SpdyFramer::GetHpackEncoder() {
3061   DCHECK_LT(SPDY3, spdy_version_);
3062   if (hpack_encoder_.get() == NULL) {
3063     hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3064   }
3065   return hpack_encoder_.get();
3066 }
3067 
GetHpackDecoder()3068 HpackDecoder* SpdyFramer::GetHpackDecoder() {
3069   DCHECK_LT(SPDY3, spdy_version_);
3070   if (hpack_decoder_.get() == NULL) {
3071     hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3072   }
3073   return hpack_decoder_.get();
3074 }
3075 
MapPriorityToWeight(SpdyPriority priority)3076 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3077   const float kSteps = 255.9f / 7.f;
3078   return static_cast<uint8>(kSteps * (7.f - priority));
3079 }
3080 
MapWeightToPriority(uint8 weight)3081 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3082   const float kSteps = 255.9f / 7.f;
3083   return static_cast<SpdyPriority>(7.f - weight / kSteps);
3084 }
3085 
3086 // Incrementally decompress the control frame's header block, feeding the
3087 // result to the visitor in chunks. Continue this until the visitor
3088 // indicates that it cannot process any more data, or (more commonly) we
3089 // run out of data to deliver.
IncrementallyDecompressControlFrameHeaderData(SpdyStreamId stream_id,const char * data,size_t len)3090 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3091     SpdyStreamId stream_id,
3092     const char* data,
3093     size_t len) {
3094   // Get a decompressor or set error.
3095   z_stream* decomp = GetHeaderDecompressor();
3096   if (decomp == NULL) {
3097     LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
3098     set_error(SPDY_DECOMPRESS_FAILURE);
3099     return false;
3100   }
3101 
3102   bool processed_successfully = true;
3103   char buffer[kHeaderDataChunkMaxSize];
3104 
3105   decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
3106   decomp->avail_in = len;
3107   // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3108   // signal an error back in ProcessControlFrameBeforeHeaderBlock.  So if we've
3109   // reached this method successfully, stream_id should be nonzero.
3110   DCHECK_LT(0u, stream_id);
3111   while (decomp->avail_in > 0 && processed_successfully) {
3112     decomp->next_out = reinterpret_cast<Bytef*>(buffer);
3113     decomp->avail_out = arraysize(buffer);
3114 
3115     int rv = inflate(decomp, Z_SYNC_FLUSH);
3116     if (rv == Z_NEED_DICT) {
3117       const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
3118                                                              : kV3Dictionary;
3119       const int dictionary_size = (protocol_version() <= SPDY2) ?
3120           kV2DictionarySize : kV3DictionarySize;
3121       const DictionaryIds& ids = g_dictionary_ids.Get();
3122       const uLong dictionary_id = (protocol_version() <= SPDY2) ?
3123           ids.v2_dictionary_id : ids.v3_dictionary_id;
3124       // Need to try again with the right dictionary.
3125       if (decomp->adler == dictionary_id) {
3126         rv = inflateSetDictionary(decomp,
3127                                   reinterpret_cast<const Bytef*>(dictionary),
3128                                   dictionary_size);
3129         if (rv == Z_OK)
3130           rv = inflate(decomp, Z_SYNC_FLUSH);
3131       }
3132     }
3133 
3134     // Inflate will generate a Z_BUF_ERROR if it runs out of input
3135     // without producing any output.  The input is consumed and
3136     // buffered internally by zlib so we can detect this condition by
3137     // checking if avail_in is 0 after the call to inflate.
3138     bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
3139     if ((rv == Z_OK) || input_exhausted) {
3140       size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
3141       if (decompressed_len > 0) {
3142         processed_successfully = visitor_->OnControlFrameHeaderData(
3143             stream_id, buffer, decompressed_len);
3144       }
3145       if (!processed_successfully) {
3146         // Assume that the problem was the header block was too large for the
3147         // visitor.
3148         set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3149       }
3150     } else {
3151       DLOG(WARNING) << "inflate failure: " << rv << " " << len;
3152       set_error(SPDY_DECOMPRESS_FAILURE);
3153       processed_successfully = false;
3154     }
3155   }
3156   return processed_successfully;
3157 }
3158 
IncrementallyDeliverControlFrameHeaderData(SpdyStreamId stream_id,const char * data,size_t len)3159 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3160     SpdyStreamId stream_id, const char* data, size_t len) {
3161   bool read_successfully = true;
3162   while (read_successfully && len > 0) {
3163     size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
3164     read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
3165                                                            bytes_to_deliver);
3166     data += bytes_to_deliver;
3167     len -= bytes_to_deliver;
3168     if (!read_successfully) {
3169       // Assume that the problem was the header block was too large for the
3170       // visitor.
3171       set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3172     }
3173   }
3174   return read_successfully;
3175 }
3176 
SerializeNameValueBlockWithoutCompression(SpdyFrameBuilder * builder,const SpdyNameValueBlock & name_value_block) const3177 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3178     SpdyFrameBuilder* builder,
3179     const SpdyNameValueBlock& name_value_block) const {
3180   // Serialize number of headers.
3181   if (protocol_version() <= SPDY2) {
3182     builder->WriteUInt16(name_value_block.size());
3183   } else {
3184     builder->WriteUInt32(name_value_block.size());
3185   }
3186 
3187   // Serialize each header.
3188   for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
3189        it != name_value_block.end();
3190        ++it) {
3191     if (protocol_version() <= SPDY2) {
3192       builder->WriteString(it->first);
3193       builder->WriteString(it->second);
3194     } else {
3195       builder->WriteStringPiece32(it->first);
3196       builder->WriteStringPiece32(it->second);
3197     }
3198   }
3199 }
3200 
SerializeNameValueBlock(SpdyFrameBuilder * builder,const SpdyFrameWithNameValueBlockIR & frame)3201 void SpdyFramer::SerializeNameValueBlock(
3202     SpdyFrameBuilder* builder,
3203     const SpdyFrameWithNameValueBlockIR& frame) {
3204   CHECK_GE(SPDY3, protocol_version());
3205   if (!enable_compression_) {
3206     return SerializeNameValueBlockWithoutCompression(builder,
3207                                                      frame.name_value_block());
3208   }
3209 
3210   // First build an uncompressed version to be fed into the compressor.
3211   const size_t uncompressed_len = GetSerializedLength(
3212       protocol_version(), &(frame.name_value_block()));
3213   SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3214   SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
3215                                             frame.name_value_block());
3216   scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
3217 
3218   z_stream* compressor = GetHeaderCompressor();
3219   if (!compressor) {
3220     LOG(DFATAL) << "Could not obtain compressor.";
3221     return;
3222   }
3223 
3224   base::StatsCounter compressed_frames("spdy.CompressedFrames");
3225   base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
3226   base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
3227 
3228   // Create an output frame.
3229   // Since we'll be performing lots of flushes when compressing the data,
3230   // zlib's lower bounds may be insufficient.
3231   //
3232   // TODO(akalin): Avoid the duplicate calculation with
3233   // GetSerializedLength(const SpdyHeaderBlock&).
3234   const int compressed_max_size =
3235       2 * deflateBound(compressor, uncompressed_len);
3236 
3237   // TODO(phajdan.jr): Clean up after we no longer need
3238   // to workaround http://crbug.com/139744.
3239 #if defined(USE_SYSTEM_ZLIB)
3240   compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
3241   compressor->avail_in = uncompressed_len;
3242 #endif  // defined(USE_SYSTEM_ZLIB)
3243   compressor->next_out = reinterpret_cast<Bytef*>(
3244       builder->GetWritableBuffer(compressed_max_size));
3245   compressor->avail_out = compressed_max_size;
3246 
3247   // TODO(phajdan.jr): Clean up after we no longer need
3248   // to workaround http://crbug.com/139744.
3249 #if defined(USE_SYSTEM_ZLIB)
3250   int rv = deflate(compressor, Z_SYNC_FLUSH);
3251   if (rv != Z_OK) {  // How can we know that it compressed everything?
3252     // This shouldn't happen, right?
3253     LOG(WARNING) << "deflate failure: " << rv;
3254     // TODO(akalin): Upstream this return.
3255     return;
3256   }
3257 #else
3258   WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
3259 #endif  // defined(USE_SYSTEM_ZLIB)
3260 
3261   int compressed_size = compressed_max_size - compressor->avail_out;
3262   builder->Seek(compressed_size);
3263   builder->RewriteLength(*this);
3264 
3265   pre_compress_bytes.Add(uncompressed_len);
3266   post_compress_bytes.Add(compressed_size);
3267 
3268   compressed_frames.Increment();
3269 }
3270 
3271 }  // namespace net
3272