Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
blob91afcd27f26ee13a0dda851b4417d34219700d13
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.
5 #include "net/spdy/spdy_framer.h"
7 #include <algorithm>
8 #include <limits>
9 #include <string>
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/third_party/valgrind/memcheck.h"
14 #include "net/spdy/spdy_frame_builder.h"
15 #include "net/spdy/spdy_frame_reader.h"
16 #include "net/spdy/spdy_bitmasks.h"
17 #include "third_party/zlib/zlib.h"
19 using base::StringPiece;
20 using std::string;
21 using std::vector;
23 namespace net {
25 namespace {
27 // Compute the id of our dictionary so that we know we're using the
28 // right one when asked for it.
29 uLong CalculateDictionaryId(const char* dictionary,
30 const size_t dictionary_size) {
31 uLong initial_value = adler32(0L, Z_NULL, 0);
32 return adler32(initial_value,
33 reinterpret_cast<const Bytef*>(dictionary),
34 dictionary_size);
37 // Check to see if the name and value of a cookie are both empty.
38 bool IsCookieEmpty(const base::StringPiece& cookie) {
39 if (cookie.size() == 0) {
40 return true;
42 size_t pos = cookie.find('=');
43 if (pos == base::StringPiece::npos) {
44 return false;
46 // Ignore leading whitespaces of cookie value.
47 size_t value_start = pos + 1;
48 for (; value_start < cookie.size(); value_start++) {
49 if (!(cookie[value_start] == ' ' || cookie[value_start] == '\t')) {
50 break;
53 return (pos == 0) && ((cookie.size() - value_start) == 0);
56 // Pack parent stream ID and exclusive flag into the format used by HTTP/2
57 // headers and priority frames.
58 uint32 PackStreamDependencyValues(bool exclusive,
59 SpdyStreamId parent_stream_id) {
60 // Make sure the highest-order bit in the parent stream id is zeroed out.
61 uint32 parent = parent_stream_id & 0x7fffffff;
62 // Set the one-bit exclusivity flag.
63 uint32 e_bit = exclusive ? 0x80000000 : 0;
64 return parent | e_bit;
67 // Unpack parent stream ID and exclusive flag from the format used by HTTP/2
68 // headers and priority frames.
69 void UnpackStreamDependencyValues(uint32 packed,
70 bool* exclusive,
71 SpdyStreamId* parent_stream_id) {
72 *exclusive = (packed >> 31) != 0;
73 // Zero out the highest-order bit to get the parent stream id.
74 *parent_stream_id = packed & 0x7fffffff;
77 struct DictionaryIds {
78 DictionaryIds()
79 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
80 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
82 const uLong v2_dictionary_id;
83 const uLong v3_dictionary_id;
86 // Adler ID for the SPDY header compressor dictionaries. Note that they are
87 // initialized lazily to avoid static initializers.
88 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
90 // Used to indicate no flags in a SPDY flags field.
91 const uint8 kNoFlags = 0;
93 // Wire sizes of priority payloads.
94 const size_t kPriorityDependencyPayloadSize = 4;
95 const size_t kPriorityWeightPayloadSize = 1;
97 // Wire size of pad length field.
98 const size_t kPadLengthFieldSize = 1;
100 } // namespace
102 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
103 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
104 // We fragment sent control frames at smaller payload boundaries.
105 const size_t SpdyFramer::kMaxControlFrameSize = 1024;
106 // The size of the control frame buffer. Must be >= the minimum size of the
107 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
108 // calculation details.
109 const size_t SpdyFramer::kControlFrameBufferSize = 19;
111 #ifdef DEBUG_SPDY_STATE_CHANGES
112 #define CHANGE_STATE(newstate) \
113 do { \
114 DVLOG(1) << "Changing state from: " \
115 << StateToString(state_) \
116 << " to " << StateToString(newstate) << "\n"; \
117 DCHECK(state_ != SPDY_ERROR); \
118 DCHECK_EQ(previous_state_, state_); \
119 previous_state_ = state_; \
120 state_ = newstate; \
121 } while (false)
122 #else
123 #define CHANGE_STATE(newstate) \
124 do { \
125 DCHECK(state_ != SPDY_ERROR); \
126 DCHECK_EQ(previous_state_, state_); \
127 previous_state_ = state_; \
128 state_ = newstate; \
129 } while (false)
130 #endif
132 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(
133 SpdyMajorVersion version, uint32 wire) {
134 if (version < SPDY3) {
135 ConvertFlagsAndIdForSpdy2(&wire);
137 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
140 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
141 : flags_(flags), id_(id & 0x00ffffff) {
142 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
145 uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version)
146 const {
147 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
148 if (version < SPDY3) {
149 ConvertFlagsAndIdForSpdy2(&wire);
151 return wire;
154 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
155 // This method is used to preserve buggy behavior and works on both
156 // little-endian and big-endian hosts.
157 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
158 // as well as vice versa).
159 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
160 uint8* wire_array = reinterpret_cast<uint8*>(val);
161 std::swap(wire_array[0], wire_array[3]);
162 std::swap(wire_array[1], wire_array[2]);
165 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
166 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
168 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
169 size_t len) {
170 return true;
173 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
174 const char* rst_stream_data,
175 size_t len) {
176 return true;
179 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
180 : current_frame_buffer_(new char[kControlFrameBufferSize]),
181 expect_continuation_(0),
182 visitor_(NULL),
183 debug_visitor_(NULL),
184 display_protocol_("SPDY"),
185 protocol_version_(version),
186 enable_compression_(true),
187 syn_frame_processed_(false),
188 probable_http_response_(false),
189 end_stream_when_done_(false),
190 header_table_size_bound_(4096) {
191 DCHECK_GE(protocol_version_, SPDY_MIN_VERSION);
192 DCHECK_LE(protocol_version_, SPDY_MAX_VERSION);
193 DCHECK_LE(kMaxControlFrameSize,
194 SpdyConstants::GetFrameMaximumSize(protocol_version_) +
195 SpdyConstants::GetControlFrameHeaderSize(protocol_version_));
196 Reset();
199 SpdyFramer::~SpdyFramer() {
200 if (header_compressor_.get()) {
201 deflateEnd(header_compressor_.get());
203 if (header_decompressor_.get()) {
204 inflateEnd(header_decompressor_.get());
208 void SpdyFramer::Reset() {
209 state_ = SPDY_RESET;
210 previous_state_ = SPDY_RESET;
211 error_code_ = SPDY_NO_ERROR;
212 remaining_data_length_ = 0;
213 remaining_control_header_ = 0;
214 current_frame_buffer_length_ = 0;
215 current_frame_type_ = DATA;
216 current_frame_flags_ = 0;
217 current_frame_length_ = 0;
218 current_frame_stream_id_ = kInvalidStream;
219 settings_scratch_.Reset();
220 altsvc_scratch_.Reset();
221 remaining_padding_payload_length_ = 0;
224 size_t SpdyFramer::GetDataFrameMinimumSize() const {
225 return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
228 // Size, in bytes, of the control frame header.
229 size_t SpdyFramer::GetControlFrameHeaderSize() const {
230 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
233 size_t SpdyFramer::GetSynStreamMinimumSize() const {
234 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
235 // name-value block.
236 if (protocol_version() <= SPDY3) {
237 // Calculated as:
238 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
239 // + 1 (unused, was credential slot)
240 return GetControlFrameHeaderSize() + 10;
241 } else {
242 return GetControlFrameHeaderSize() +
243 kPriorityDependencyPayloadSize +
244 kPriorityWeightPayloadSize;
248 size_t SpdyFramer::GetSynReplyMinimumSize() const {
249 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
250 // name-value block.
251 size_t size = GetControlFrameHeaderSize();
252 if (protocol_version() <= SPDY3) {
253 // Calculated as:
254 // control frame header + 4 (stream IDs)
255 size += 4;
258 // In SPDY 2, there were 2 unused bytes before payload.
259 if (protocol_version() < SPDY3) {
260 size += 2;
263 return size;
266 size_t SpdyFramer::GetRstStreamMinimumSize() const {
267 // Size, in bytes, of a RST_STREAM frame.
268 if (protocol_version() <= SPDY3) {
269 // Calculated as:
270 // control frame header + 4 (stream id) + 4 (status code)
271 return GetControlFrameHeaderSize() + 8;
272 } else {
273 // Calculated as:
274 // frame prefix + 4 (status code)
275 return GetControlFrameHeaderSize() + 4;
279 size_t SpdyFramer::GetSettingsMinimumSize() const {
280 // Size, in bytes, of a SETTINGS frame not including the IDs and values
281 // from the variable-length value block. Calculated as:
282 // control frame header + 4 (number of ID/value pairs)
283 if (protocol_version() <= SPDY3) {
284 return GetControlFrameHeaderSize() + 4;
285 } else {
286 return GetControlFrameHeaderSize();
290 size_t SpdyFramer::GetPingSize() const {
291 // Size, in bytes, of this PING frame.
292 if (protocol_version() <= SPDY3) {
293 // Calculated as:
294 // control frame header + 4 (id)
295 return GetControlFrameHeaderSize() + 4;
296 } else {
297 // Calculated as:
298 // control frame header + 8 (id)
299 return GetControlFrameHeaderSize() + 8;
303 size_t SpdyFramer::GetGoAwayMinimumSize() const {
304 // Size, in bytes, of this GOAWAY frame. Calculated as:
305 // 1. Control frame header size
306 size_t size = GetControlFrameHeaderSize();
308 // 2. Last good stream id (4 bytes)
309 size += 4;
311 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
312 if (protocol_version() >= SPDY3) {
313 size += 4;
316 return size;
319 size_t SpdyFramer::GetHeadersMinimumSize() const {
320 // Size, in bytes, of a HEADERS frame not including the variable-length
321 // name-value block.
322 size_t size = GetControlFrameHeaderSize();
323 if (protocol_version() <= SPDY3) {
324 // Calculated as:
325 // control frame header + 4 (stream IDs)
326 size += 4;
329 // In SPDY 2, there were 2 unused bytes before payload.
330 if (protocol_version() <= SPDY2) {
331 size += 2;
334 return size;
337 size_t SpdyFramer::GetWindowUpdateSize() const {
338 // Size, in bytes, of a WINDOW_UPDATE frame.
339 if (protocol_version() <= SPDY3) {
340 // Calculated as:
341 // control frame header + 4 (stream id) + 4 (delta)
342 return GetControlFrameHeaderSize() + 8;
343 } else {
344 // Calculated as:
345 // frame prefix + 4 (delta)
346 return GetControlFrameHeaderSize() + 4;
350 size_t SpdyFramer::GetBlockedSize() const {
351 DCHECK_LT(SPDY3, protocol_version());
352 // Size, in bytes, of a BLOCKED frame.
353 // The BLOCKED frame has no payload beyond the control frame header.
354 return GetControlFrameHeaderSize();
357 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
358 DCHECK_LT(SPDY3, protocol_version());
359 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
360 // Calculated as frame prefix + 4 (promised stream id).
361 return GetControlFrameHeaderSize() + 4;
364 size_t SpdyFramer::GetContinuationMinimumSize() const {
365 // Size, in bytes, of a CONTINUATION frame not including the variable-length
366 // headers fragments.
367 return GetControlFrameHeaderSize();
370 size_t SpdyFramer::GetAltSvcMinimumSize() const {
371 // Size, in bytes, of an ALTSVC frame not including the Field-Value and
372 // (optional) Origin fields, both of which can vary in length. Note that this
373 // gives a lower bound on the frame size rather than a true minimum; the
374 // actual frame should always be larger than this.
375 // Calculated as frame prefix + 2 (origin_len).
376 return GetControlFrameHeaderSize() + 2;
379 size_t SpdyFramer::GetPrioritySize() const {
380 // Size, in bytes, of a PRIORITY frame.
381 return GetControlFrameHeaderSize() +
382 kPriorityDependencyPayloadSize +
383 kPriorityWeightPayloadSize;
386 size_t SpdyFramer::GetFrameMinimumSize() const {
387 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
390 size_t SpdyFramer::GetFrameMaximumSize() const {
391 return SpdyConstants::GetFrameMaximumSize(protocol_version());
394 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
395 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
398 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
399 return SpdyConstants::GetPrefixLength(type, protocol_version());
402 const char* SpdyFramer::StateToString(int state) {
403 switch (state) {
404 case SPDY_ERROR:
405 return "ERROR";
406 case SPDY_AUTO_RESET:
407 return "AUTO_RESET";
408 case SPDY_RESET:
409 return "RESET";
410 case SPDY_READING_COMMON_HEADER:
411 return "READING_COMMON_HEADER";
412 case SPDY_CONTROL_FRAME_PAYLOAD:
413 return "CONTROL_FRAME_PAYLOAD";
414 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
415 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
416 case SPDY_CONSUME_PADDING:
417 return "SPDY_CONSUME_PADDING";
418 case SPDY_IGNORE_REMAINING_PAYLOAD:
419 return "IGNORE_REMAINING_PAYLOAD";
420 case SPDY_FORWARD_STREAM_FRAME:
421 return "FORWARD_STREAM_FRAME";
422 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
423 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
424 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
425 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
426 case SPDY_GOAWAY_FRAME_PAYLOAD:
427 return "SPDY_GOAWAY_FRAME_PAYLOAD";
428 case SPDY_RST_STREAM_FRAME_PAYLOAD:
429 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
430 case SPDY_SETTINGS_FRAME_PAYLOAD:
431 return "SPDY_SETTINGS_FRAME_PAYLOAD";
432 case SPDY_ALTSVC_FRAME_PAYLOAD:
433 return "SPDY_ALTSVC_FRAME_PAYLOAD";
435 return "UNKNOWN_STATE";
438 void SpdyFramer::set_error(SpdyError error) {
439 DCHECK(visitor_);
440 error_code_ = error;
441 // These values will usually get reset once we come to the end
442 // of a header block, but if we run into an error that
443 // might not happen, so reset them here.
444 expect_continuation_ = 0;
445 end_stream_when_done_ = false;
447 CHANGE_STATE(SPDY_ERROR);
448 visitor_->OnError(this);
451 const char* SpdyFramer::ErrorCodeToString(int error_code) {
452 switch (error_code) {
453 case SPDY_NO_ERROR:
454 return "NO_ERROR";
455 case SPDY_INVALID_CONTROL_FRAME:
456 return "INVALID_CONTROL_FRAME";
457 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
458 return "CONTROL_PAYLOAD_TOO_LARGE";
459 case SPDY_ZLIB_INIT_FAILURE:
460 return "ZLIB_INIT_FAILURE";
461 case SPDY_UNSUPPORTED_VERSION:
462 return "UNSUPPORTED_VERSION";
463 case SPDY_DECOMPRESS_FAILURE:
464 return "DECOMPRESS_FAILURE";
465 case SPDY_COMPRESS_FAILURE:
466 return "COMPRESS_FAILURE";
467 case SPDY_INVALID_DATA_FRAME_FLAGS:
468 return "SPDY_INVALID_DATA_FRAME_FLAGS";
469 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
470 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
471 case SPDY_UNEXPECTED_FRAME:
472 return "UNEXPECTED_FRAME";
474 return "UNKNOWN_ERROR";
477 const char* SpdyFramer::StatusCodeToString(int status_code) {
478 switch (status_code) {
479 case RST_STREAM_INVALID:
480 return "INVALID";
481 case RST_STREAM_PROTOCOL_ERROR:
482 return "PROTOCOL_ERROR";
483 case RST_STREAM_INVALID_STREAM:
484 return "INVALID_STREAM";
485 case RST_STREAM_REFUSED_STREAM:
486 return "REFUSED_STREAM";
487 case RST_STREAM_UNSUPPORTED_VERSION:
488 return "UNSUPPORTED_VERSION";
489 case RST_STREAM_CANCEL:
490 return "CANCEL";
491 case RST_STREAM_INTERNAL_ERROR:
492 return "INTERNAL_ERROR";
493 case RST_STREAM_FLOW_CONTROL_ERROR:
494 return "FLOW_CONTROL_ERROR";
495 case RST_STREAM_STREAM_IN_USE:
496 return "STREAM_IN_USE";
497 case RST_STREAM_STREAM_ALREADY_CLOSED:
498 return "STREAM_ALREADY_CLOSED";
499 case RST_STREAM_INVALID_CREDENTIALS:
500 return "INVALID_CREDENTIALS";
501 case RST_STREAM_FRAME_TOO_LARGE:
502 return "FRAME_TOO_LARGE";
503 case RST_STREAM_CONNECT_ERROR:
504 return "CONNECT_ERROR";
505 case RST_STREAM_ENHANCE_YOUR_CALM:
506 return "ENHANCE_YOUR_CALM";
507 case RST_STREAM_INADEQUATE_SECURITY:
508 return "INADEQUATE_SECURITY";
509 case RST_STREAM_HTTP_1_1_REQUIRED:
510 return "HTTP_1_1_REQUIRED";
512 return "UNKNOWN_STATUS";
515 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
516 switch (type) {
517 case DATA:
518 return "DATA";
519 case SYN_STREAM:
520 return "SYN_STREAM";
521 case SYN_REPLY:
522 return "SYN_REPLY";
523 case RST_STREAM:
524 return "RST_STREAM";
525 case SETTINGS:
526 return "SETTINGS";
527 case PING:
528 return "PING";
529 case GOAWAY:
530 return "GOAWAY";
531 case HEADERS:
532 return "HEADERS";
533 case WINDOW_UPDATE:
534 return "WINDOW_UPDATE";
535 case CREDENTIAL:
536 return "CREDENTIAL";
537 case PUSH_PROMISE:
538 return "PUSH_PROMISE";
539 case CONTINUATION:
540 return "CONTINUATION";
541 case PRIORITY:
542 return "PRIORITY";
543 case ALTSVC:
544 return "ALTSVC";
545 case BLOCKED:
546 return "BLOCKED";
548 return "UNKNOWN_CONTROL_TYPE";
551 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
552 DCHECK(visitor_);
553 DCHECK(data);
555 size_t original_len = len;
556 do {
557 previous_state_ = state_;
558 switch (state_) {
559 case SPDY_ERROR:
560 goto bottom;
562 case SPDY_AUTO_RESET:
563 case SPDY_RESET:
564 Reset();
565 if (len > 0) {
566 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
568 break;
570 case SPDY_READING_COMMON_HEADER: {
571 size_t bytes_read = ProcessCommonHeader(data, len);
572 len -= bytes_read;
573 data += bytes_read;
574 break;
577 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
578 // Control frames that contain header blocks
579 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
580 // take a different path through the state machine - they
581 // will go:
582 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
583 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
585 // SETTINGS frames take a slightly modified route:
586 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
587 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
589 // All other control frames will use the alternate route directly to
590 // SPDY_CONTROL_FRAME_PAYLOAD
591 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
592 len -= bytes_read;
593 data += bytes_read;
594 break;
597 case SPDY_SETTINGS_FRAME_PAYLOAD: {
598 int bytes_read = ProcessSettingsFramePayload(data, len);
599 len -= bytes_read;
600 data += bytes_read;
601 break;
604 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
605 int bytes_read = ProcessControlFrameHeaderBlock(
606 data, len, protocol_version() > SPDY3);
607 len -= bytes_read;
608 data += bytes_read;
609 break;
612 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
613 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
614 len -= bytes_read;
615 data += bytes_read;
616 break;
619 case SPDY_GOAWAY_FRAME_PAYLOAD: {
620 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
621 len -= bytes_read;
622 data += bytes_read;
623 break;
626 case SPDY_ALTSVC_FRAME_PAYLOAD: {
627 size_t bytes_read = ProcessAltSvcFramePayload(data, len);
628 len -= bytes_read;
629 data += bytes_read;
630 break;
633 case SPDY_CONTROL_FRAME_PAYLOAD: {
634 size_t bytes_read = ProcessControlFramePayload(data, len);
635 len -= bytes_read;
636 data += bytes_read;
637 break;
640 case SPDY_READ_DATA_FRAME_PADDING_LENGTH: {
641 size_t bytes_read = ProcessDataFramePaddingLength(data, len);
642 len -= bytes_read;
643 data += bytes_read;
644 break;
647 case SPDY_CONSUME_PADDING: {
648 size_t bytes_read = ProcessFramePadding(data, len);
649 len -= bytes_read;
650 data += bytes_read;
651 break;
654 case SPDY_IGNORE_REMAINING_PAYLOAD: {
655 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
656 len -= bytes_read;
657 data += bytes_read;
658 break;
661 case SPDY_FORWARD_STREAM_FRAME: {
662 size_t bytes_read = ProcessDataFramePayload(data, len);
663 len -= bytes_read;
664 data += bytes_read;
665 break;
668 default:
669 LOG(DFATAL) << "Invalid value for " << display_protocol_
670 << " framer state: " << state_;
671 // This ensures that we don't infinite-loop if state_ gets an
672 // invalid value somehow, such as due to a SpdyFramer getting deleted
673 // from a callback it calls.
674 goto bottom;
676 } while (state_ != previous_state_);
677 bottom:
678 DCHECK(len == 0 || state_ == SPDY_ERROR);
679 if (current_frame_buffer_length_ == 0 &&
680 remaining_data_length_ == 0 &&
681 remaining_control_header_ == 0) {
682 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
683 << "State: " << StateToString(state_);
686 return original_len - len;
689 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
690 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
691 // state.
692 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
694 size_t original_len = len;
696 // Update current frame buffer as needed.
697 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
698 size_t bytes_desired =
699 GetControlFrameHeaderSize() - current_frame_buffer_length_;
700 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
703 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
704 // Not enough information to do anything meaningful.
705 return original_len - len;
708 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
709 // when processing DATA frames below.
710 scoped_ptr<SpdyFrameReader> reader(
711 new SpdyFrameReader(current_frame_buffer_.get(),
712 current_frame_buffer_length_));
714 bool is_control_frame = false;
716 int control_frame_type_field =
717 SpdyConstants::DataFrameType(protocol_version());
718 // ProcessControlFrameHeader() will set current_frame_type_ to the
719 // correct value if this is a valid control frame.
720 current_frame_type_ = DATA;
721 if (protocol_version() <= SPDY3) {
722 uint16 version = 0;
723 bool successful_read = reader->ReadUInt16(&version);
724 DCHECK(successful_read);
725 is_control_frame = (version & kControlFlagMask) != 0;
726 version &= ~kControlFlagMask; // Only valid for control frames.
727 if (is_control_frame) {
728 // We check version before we check validity: version can never be
729 // 'invalid', it can only be unsupported.
730 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
731 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
732 SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
733 // Version does not match the version the framer was initialized with.
734 DVLOG(1) << "Unsupported SPDY version "
735 << version
736 << " (expected " << protocol_version() << ")";
737 set_error(SPDY_UNSUPPORTED_VERSION);
738 return 0;
740 // We check control_frame_type_field's validity in
741 // ProcessControlFrameHeader().
742 uint16 control_frame_type_field_uint16;
743 successful_read = reader->ReadUInt16(&control_frame_type_field_uint16);
744 control_frame_type_field = control_frame_type_field_uint16;
745 } else {
746 reader->Rewind();
747 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
749 DCHECK(successful_read);
751 successful_read = reader->ReadUInt8(&current_frame_flags_);
752 DCHECK(successful_read);
754 uint32 length_field = 0;
755 successful_read = reader->ReadUInt24(&length_field);
756 DCHECK(successful_read);
757 remaining_data_length_ = length_field;
758 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
759 } else {
760 uint32 length_field = 0;
761 bool successful_read = reader->ReadUInt24(&length_field);
762 DCHECK(successful_read);
764 uint8 control_frame_type_field_uint8;
765 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
766 DCHECK(successful_read);
767 // We check control_frame_type_field's validity in
768 // ProcessControlFrameHeader().
769 control_frame_type_field = control_frame_type_field_uint8;
770 is_control_frame = control_frame_type_field !=
771 SpdyConstants::SerializeFrameType(protocol_version(), DATA);
773 if (is_control_frame) {
774 current_frame_length_ = length_field + GetControlFrameHeaderSize();
775 } else {
776 current_frame_length_ = length_field + GetDataFrameMinimumSize();
779 successful_read = reader->ReadUInt8(&current_frame_flags_);
780 DCHECK(successful_read);
782 successful_read = reader->ReadUInt31(&current_frame_stream_id_);
783 DCHECK(successful_read);
785 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
787 // Before we accept a DATA frame, we need to make sure we're not in the
788 // middle of processing a header block.
789 const bool is_continuation_frame = (control_frame_type_field ==
790 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
791 if ((expect_continuation_ != 0) != is_continuation_frame) {
792 if (expect_continuation_ != 0) {
793 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
794 << "frame, but instead received frame type "
795 << control_frame_type_field;
796 } else {
797 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
799 set_error(SPDY_UNEXPECTED_FRAME);
800 return original_len - len;
803 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
804 : GetDataFrameMinimumSize(),
805 reader->GetBytesConsumed());
806 DCHECK_EQ(current_frame_length_,
807 remaining_data_length_ + reader->GetBytesConsumed());
809 // This is just a sanity check for help debugging early frame errors.
810 if (remaining_data_length_ > 1000000u) {
811 // The strncmp for 5 is safe because we only hit this point if we
812 // have kMinCommonHeader (8) bytes
813 if (!syn_frame_processed_ &&
814 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
815 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
816 << " request";
817 probable_http_response_ = true;
818 } else {
819 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
820 << " session is likely corrupt.";
824 // if we're here, then we have the common header all received.
825 if (!is_control_frame) {
826 if (protocol_version() > SPDY3) {
827 // Catch bogus tests sending oversized DATA frames.
828 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
829 << "DATA frame too large for SPDY >= 4.";
832 uint8 valid_data_flags = 0;
833 if (protocol_version() > SPDY3) {
834 valid_data_flags =
835 DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED;
836 } else {
837 valid_data_flags = DATA_FLAG_FIN;
840 if (current_frame_flags_ & ~valid_data_flags) {
841 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
842 } else {
843 visitor_->OnDataFrameHeader(current_frame_stream_id_,
844 remaining_data_length_,
845 current_frame_flags_ & DATA_FLAG_FIN);
846 if (remaining_data_length_ > 0) {
847 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH);
848 } else {
849 // Empty data frame.
850 if (current_frame_flags_ & DATA_FLAG_FIN) {
851 visitor_->OnStreamFrameData(
852 current_frame_stream_id_, NULL, 0, true);
854 CHANGE_STATE(SPDY_AUTO_RESET);
857 } else {
858 ProcessControlFrameHeader(control_frame_type_field);
861 return original_len - len;
864 void SpdyFramer::ProcessControlFrameHeader(int control_frame_type_field) {
865 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
866 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
868 // TODO(mlavan): Either remove credential frames from the code entirely,
869 // or add them to parsing + serialization methods for SPDY3.
870 // Early detection of deprecated frames that we ignore.
871 if (protocol_version() <= SPDY3) {
872 if (control_frame_type_field == CREDENTIAL) {
873 current_frame_type_ = CREDENTIAL;
874 DCHECK_EQ(SPDY3, protocol_version());
875 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
876 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
877 return;
881 if (!SpdyConstants::IsValidFrameType(protocol_version(),
882 control_frame_type_field)) {
883 if (protocol_version() <= SPDY3) {
884 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
885 << " (protocol version: " << protocol_version() << ")";
886 set_error(SPDY_INVALID_CONTROL_FRAME);
887 return;
888 } else {
889 // In HTTP2 we ignore unknown frame types for extensibility, as long as
890 // the rest of the control frame header is valid.
891 // We rely on the visitor to check validity of current_frame_stream_id_.
892 bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_,
893 control_frame_type_field);
894 if (valid_stream) {
895 DVLOG(1) << "Ignoring unknown frame type.";
896 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
897 } else {
898 // Report an invalid frame error and close the stream if the
899 // stream_id is not valid.
900 DLOG(WARNING) << "Unknown control frame type "
901 << control_frame_type_field
902 << " received on invalid stream "
903 << current_frame_stream_id_;
904 set_error(SPDY_INVALID_CONTROL_FRAME);
906 return;
910 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
911 control_frame_type_field);
913 // Do some sanity checking on the control frame sizes and flags.
914 switch (current_frame_type_) {
915 case SYN_STREAM:
916 if (current_frame_length_ < GetSynStreamMinimumSize()) {
917 set_error(SPDY_INVALID_CONTROL_FRAME);
918 } else if (current_frame_flags_ &
919 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
920 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
922 break;
923 case SYN_REPLY:
924 if (current_frame_length_ < GetSynReplyMinimumSize()) {
925 set_error(SPDY_INVALID_CONTROL_FRAME);
926 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
927 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
929 break;
930 case RST_STREAM:
931 // For SPDY versions < 4, the header has a fixed length.
932 // For SPDY version 4 and up, the RST_STREAM frame may include optional
933 // opaque data, so we only have a lower limit on the frame size.
934 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
935 protocol_version() <= SPDY3) ||
936 (current_frame_length_ < GetRstStreamMinimumSize() &&
937 protocol_version() > SPDY3)) {
938 set_error(SPDY_INVALID_CONTROL_FRAME);
939 } else if (current_frame_flags_ != 0) {
940 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
942 break;
943 case SETTINGS:
945 // Make sure that we have an integral number of 8-byte key/value pairs,
946 // plus a 4-byte length field in SPDY3 and below.
947 size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
948 // Size of each key/value pair in bytes.
949 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
950 if (current_frame_length_ < GetSettingsMinimumSize() ||
951 (current_frame_length_ - GetControlFrameHeaderSize())
952 % setting_size != values_prefix_size) {
953 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
954 << current_frame_length_;
955 set_error(SPDY_INVALID_CONTROL_FRAME);
956 } else if (protocol_version() <= SPDY3 &&
957 current_frame_flags_ &
958 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
959 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
960 } else if (protocol_version() > SPDY3 &&
961 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
962 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
963 } else if (protocol_version() > SPDY3 &&
964 current_frame_flags_ & SETTINGS_FLAG_ACK &&
965 current_frame_length_ > GetSettingsMinimumSize()) {
966 set_error(SPDY_INVALID_CONTROL_FRAME);
968 break;
970 case PING:
971 if (current_frame_length_ != GetPingSize()) {
972 set_error(SPDY_INVALID_CONTROL_FRAME);
973 } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
974 (current_frame_flags_ & ~PING_FLAG_ACK)) {
975 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
977 break;
978 case GOAWAY:
980 // For SPDY version < 4, there are only mandatory fields and the header
981 // has a fixed length. For SPDY version >= 4, optional opaque data may
982 // be appended to the GOAWAY frame, thus there is only a minimal length
983 // restriction.
984 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
985 protocol_version() <= SPDY3) ||
986 (current_frame_length_ < GetGoAwayMinimumSize() &&
987 protocol_version() > SPDY3)) {
988 set_error(SPDY_INVALID_CONTROL_FRAME);
989 } else if (current_frame_flags_ != 0) {
990 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
992 break;
994 case HEADERS:
996 size_t min_size = GetHeadersMinimumSize();
997 if (protocol_version() > SPDY3 &&
998 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
999 min_size += 4;
1001 if (current_frame_length_ < min_size) {
1002 // TODO(mlavan): check here for HEADERS with no payload?
1003 // (not allowed in HTTP2)
1004 set_error(SPDY_INVALID_CONTROL_FRAME);
1005 } else if (protocol_version() <= SPDY3 &&
1006 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
1007 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1008 } else if (protocol_version() > SPDY3 &&
1009 current_frame_flags_ &
1010 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
1011 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
1012 HEADERS_FLAG_PADDED)) {
1013 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1016 break;
1017 case WINDOW_UPDATE:
1018 if (current_frame_length_ != GetWindowUpdateSize()) {
1019 set_error(SPDY_INVALID_CONTROL_FRAME);
1020 } else if (current_frame_flags_ != 0) {
1021 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1023 break;
1024 case BLOCKED:
1025 if (current_frame_length_ != GetBlockedSize() ||
1026 protocol_version() <= SPDY3) {
1027 set_error(SPDY_INVALID_CONTROL_FRAME);
1028 } else if (current_frame_flags_ != 0) {
1029 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1031 break;
1032 case PUSH_PROMISE:
1033 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
1034 set_error(SPDY_INVALID_CONTROL_FRAME);
1035 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
1036 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1037 } else if (protocol_version() > SPDY3 &&
1038 current_frame_flags_ &
1039 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
1040 HEADERS_FLAG_PADDED)) {
1041 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1043 break;
1044 case CONTINUATION:
1045 if (current_frame_length_ < GetContinuationMinimumSize() ||
1046 protocol_version() <= SPDY3) {
1047 set_error(SPDY_INVALID_CONTROL_FRAME);
1048 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
1049 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1051 break;
1052 case ALTSVC:
1053 if (current_frame_length_ <= GetAltSvcMinimumSize()) {
1054 set_error(SPDY_INVALID_CONTROL_FRAME);
1055 } else if (current_frame_flags_ != 0) {
1056 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1058 break;
1059 case PRIORITY:
1060 if (current_frame_length_ != GetPrioritySize() ||
1061 protocol_version() <= SPDY3) {
1062 set_error(SPDY_INVALID_CONTROL_FRAME);
1063 } else if (current_frame_flags_ != 0) {
1064 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
1066 break;
1067 default:
1068 LOG(WARNING) << "Valid " << display_protocol_
1069 << " control frame with unhandled type: "
1070 << current_frame_type_;
1071 // This branch should be unreachable because of the frame type bounds
1072 // check above. However, we DLOG(FATAL) here in an effort to painfully
1073 // club the head of the developer who failed to keep this file in sync
1074 // with spdy_protocol.h.
1075 DLOG(FATAL);
1076 set_error(SPDY_INVALID_CONTROL_FRAME);
1077 break;
1080 if (state_ == SPDY_ERROR) {
1081 return;
1084 if (current_frame_length_ >
1085 SpdyConstants::GetFrameMaximumSize(protocol_version()) +
1086 SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
1087 DLOG(WARNING) << "Received control frame of type " << current_frame_type_
1088 << " with way too big of a payload: "
1089 << current_frame_length_;
1090 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1091 return;
1094 if (current_frame_type_ == GOAWAY) {
1095 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
1096 return;
1099 if (current_frame_type_ == RST_STREAM) {
1100 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
1101 return;
1104 if (current_frame_type_ == ALTSVC) {
1105 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1106 return;
1108 // Determine the frame size without variable-length data.
1109 int32 frame_size_without_variable_data;
1110 switch (current_frame_type_) {
1111 case SYN_STREAM:
1112 syn_frame_processed_ = true;
1113 frame_size_without_variable_data = GetSynStreamMinimumSize();
1114 break;
1115 case SYN_REPLY:
1116 syn_frame_processed_ = true;
1117 frame_size_without_variable_data = GetSynReplyMinimumSize();
1118 break;
1119 case SETTINGS:
1120 frame_size_without_variable_data = GetSettingsMinimumSize();
1121 break;
1122 case HEADERS:
1123 frame_size_without_variable_data = GetHeadersMinimumSize();
1124 if (protocol_version() > SPDY3) {
1125 if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
1126 frame_size_without_variable_data += kPadLengthFieldSize;
1128 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1129 frame_size_without_variable_data +=
1130 kPriorityDependencyPayloadSize +
1131 kPriorityWeightPayloadSize;
1134 break;
1135 case PUSH_PROMISE:
1136 frame_size_without_variable_data = GetPushPromiseMinimumSize();
1137 if (protocol_version() > SPDY3 &&
1138 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1139 frame_size_without_variable_data += kPadLengthFieldSize;
1141 break;
1142 case CONTINUATION:
1143 frame_size_without_variable_data = GetContinuationMinimumSize();
1144 break;
1145 default:
1146 frame_size_without_variable_data = -1;
1147 break;
1150 if ((frame_size_without_variable_data == -1) &&
1151 (current_frame_length_ > kControlFrameBufferSize)) {
1152 // We should already be in an error state. Double-check.
1153 DCHECK_EQ(SPDY_ERROR, state_);
1154 if (state_ != SPDY_ERROR) {
1155 LOG(DFATAL) << display_protocol_
1156 << " control frame buffer too small for fixed-length frame.";
1157 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1159 return;
1162 if (frame_size_without_variable_data > 0) {
1163 // We have a control frame with a header block. We need to parse the
1164 // remainder of the control frame's header before we can parse the header
1165 // block. The start of the header block varies with the control type.
1166 DCHECK_GE(frame_size_without_variable_data,
1167 static_cast<int32>(current_frame_buffer_length_));
1168 remaining_control_header_ = frame_size_without_variable_data -
1169 current_frame_buffer_length_;
1171 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
1172 return;
1175 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
1178 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
1179 size_t max_bytes) {
1180 size_t bytes_to_read = std::min(*len, max_bytes);
1181 if (bytes_to_read > 0) {
1182 DCHECK_GE(kControlFrameBufferSize,
1183 current_frame_buffer_length_ + bytes_to_read);
1184 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
1185 *data,
1186 bytes_to_read);
1187 current_frame_buffer_length_ += bytes_to_read;
1188 *data += bytes_to_read;
1189 *len -= bytes_to_read;
1191 return bytes_to_read;
1194 size_t SpdyFramer::GetSerializedLength(
1195 const SpdyMajorVersion spdy_version,
1196 const SpdyHeaderBlock* headers) {
1197 const size_t num_name_value_pairs_size
1198 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
1199 const size_t length_of_name_size = num_name_value_pairs_size;
1200 const size_t length_of_value_size = num_name_value_pairs_size;
1202 size_t total_length = num_name_value_pairs_size;
1203 for (SpdyHeaderBlock::const_iterator it = headers->begin();
1204 it != headers->end();
1205 ++it) {
1206 // We add space for the length of the name and the length of the value as
1207 // well as the length of the name and the length of the value.
1208 total_length += length_of_name_size + it->first.size() +
1209 length_of_value_size + it->second.size();
1211 return total_length;
1214 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
1215 const SpdyMajorVersion spdy_version,
1216 const SpdyHeaderBlock* headers) {
1217 if (spdy_version < SPDY3) {
1218 frame->WriteUInt16(static_cast<uint16>(headers->size()));
1219 } else {
1220 frame->WriteUInt32(headers->size());
1222 SpdyHeaderBlock::const_iterator it;
1223 for (it = headers->begin(); it != headers->end(); ++it) {
1224 if (spdy_version < SPDY3) {
1225 frame->WriteStringPiece16(it->first);
1226 frame->WriteStringPiece16(it->second);
1227 } else {
1228 frame->WriteStringPiece32(it->first);
1229 frame->WriteStringPiece32(it->second);
1234 // TODO(phajdan.jr): Clean up after we no longer need
1235 // to workaround http://crbug.com/139744.
1236 #if !defined(USE_SYSTEM_ZLIB)
1238 // These constants are used by zlib to differentiate between normal data and
1239 // cookie data. Cookie data is handled specially by zlib when compressing.
1240 enum ZDataClass {
1241 // kZStandardData is compressed normally, save that it will never match
1242 // against any other class of data in the window.
1243 kZStandardData = Z_CLASS_STANDARD,
1244 // kZCookieData is compressed in its own Huffman blocks and only matches in
1245 // its entirety and only against other kZCookieData blocks. Any matches must
1246 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1247 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1248 // prefix matches.
1249 kZCookieData = Z_CLASS_COOKIE,
1250 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1251 // against the window.
1252 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
1255 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1256 // needed when switching between classes of data.
1257 static void WriteZ(const base::StringPiece& data,
1258 ZDataClass clas,
1259 z_stream* out) {
1260 int rv;
1262 // If we are switching from standard to non-standard data then we need to end
1263 // the current Huffman context to avoid it leaking between them.
1264 if (out->clas == kZStandardData &&
1265 clas != kZStandardData) {
1266 out->avail_in = 0;
1267 rv = deflate(out, Z_PARTIAL_FLUSH);
1268 DCHECK_EQ(Z_OK, rv);
1269 DCHECK_EQ(0u, out->avail_in);
1270 DCHECK_LT(0u, out->avail_out);
1273 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1274 out->avail_in = data.size();
1275 out->clas = clas;
1276 if (clas == kZStandardData) {
1277 rv = deflate(out, Z_NO_FLUSH);
1278 } else {
1279 rv = deflate(out, Z_PARTIAL_FLUSH);
1281 if (!data.empty()) {
1282 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1283 DCHECK_EQ(Z_OK, rv);
1285 DCHECK_EQ(0u, out->avail_in);
1286 DCHECK_LT(0u, out->avail_out);
1289 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1290 static void WriteLengthZ(size_t n,
1291 unsigned length,
1292 ZDataClass clas,
1293 z_stream* out) {
1294 char buf[4];
1295 DCHECK_LE(length, sizeof(buf));
1296 for (unsigned i = 1; i <= length; i++) {
1297 buf[length - i] = static_cast<char>(n);
1298 n >>= 8;
1300 WriteZ(base::StringPiece(buf, length), clas, out);
1303 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1304 // manner that resists the length of the compressed data from compromising
1305 // cookie data.
1306 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1307 z_stream* z) const {
1308 unsigned length_length = 4;
1309 if (protocol_version() < 3)
1310 length_length = 2;
1312 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1314 std::map<std::string, std::string>::const_iterator it;
1315 for (it = headers->begin(); it != headers->end(); ++it) {
1316 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1317 WriteZ(it->first, kZStandardData, z);
1319 if (it->first == "cookie") {
1320 // We require the cookie values (save for the last) to end with a
1321 // semicolon and (save for the first) to start with a space. This is
1322 // typically the format that we are given them in but we reserialize them
1323 // to be sure.
1325 std::vector<base::StringPiece> cookie_values;
1326 size_t cookie_length = 0;
1327 base::StringPiece cookie_data(it->second);
1329 for (;;) {
1330 while (!cookie_data.empty() &&
1331 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1332 cookie_data.remove_prefix(1);
1334 if (cookie_data.empty())
1335 break;
1337 size_t i;
1338 for (i = 0; i < cookie_data.size(); i++) {
1339 if (cookie_data[i] == ';')
1340 break;
1342 if (i < cookie_data.size()) {
1343 if (!IsCookieEmpty(cookie_data.substr(0, i))) {
1344 cookie_values.push_back(cookie_data.substr(0, i));
1345 cookie_length += i + 2 /* semicolon and space */;
1347 cookie_data.remove_prefix(i + 1);
1348 } else {
1349 if (!IsCookieEmpty(cookie_data)) {
1350 cookie_values.push_back(cookie_data);
1351 cookie_length += cookie_data.size();
1352 } else if (cookie_length > 2) {
1353 cookie_length -= 2 /* compensate for previously added length */;
1355 cookie_data.remove_prefix(i);
1359 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1360 for (size_t i = 0; i < cookie_values.size(); i++) {
1361 std::string cookie;
1362 // Since zlib will only back-reference complete cookies, a cookie that
1363 // is currently last (and so doesn't have a trailing semicolon) won't
1364 // match if it's later in a non-final position. The same is true of
1365 // the first cookie.
1366 if (i == 0 && cookie_values.size() == 1) {
1367 cookie = cookie_values[i].as_string();
1368 } else if (i == 0) {
1369 cookie = cookie_values[i].as_string() + ";";
1370 } else if (i < cookie_values.size() - 1) {
1371 cookie = " " + cookie_values[i].as_string() + ";";
1372 } else {
1373 cookie = " " + cookie_values[i].as_string();
1375 WriteZ(cookie, kZCookieData, z);
1377 } else if (it->first == "accept" ||
1378 it->first == "accept-charset" ||
1379 it->first == "accept-encoding" ||
1380 it->first == "accept-language" ||
1381 it->first == "host" ||
1382 it->first == "version" ||
1383 it->first == "method" ||
1384 it->first == "scheme" ||
1385 it->first == ":host" ||
1386 it->first == ":version" ||
1387 it->first == ":method" ||
1388 it->first == ":scheme" ||
1389 it->first == "user-agent") {
1390 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1391 WriteZ(it->second, kZStandardData, z);
1392 } else {
1393 // Non-whitelisted headers are Huffman compressed in their own block, but
1394 // don't match against the window.
1395 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1396 WriteZ(it->second, kZHuffmanOnlyData, z);
1400 z->avail_in = 0;
1401 int rv = deflate(z, Z_SYNC_FLUSH);
1402 DCHECK_EQ(Z_OK, rv);
1403 z->clas = kZStandardData;
1406 #endif // !defined(USE_SYSTEM_ZLIB)
1408 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1409 size_t len) {
1410 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1411 const size_t original_len = len;
1413 if (remaining_control_header_ > 0) {
1414 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1415 remaining_control_header_);
1416 remaining_control_header_ -= bytes_read;
1417 remaining_data_length_ -= bytes_read;
1420 if (remaining_control_header_ == 0) {
1421 SpdyFrameReader reader(current_frame_buffer_.get(),
1422 current_frame_buffer_length_);
1423 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1425 switch (current_frame_type_) {
1426 case SYN_STREAM:
1428 DCHECK_GE(SPDY3, protocol_version());
1429 bool successful_read = true;
1430 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1431 DCHECK(successful_read);
1432 if (current_frame_stream_id_ == 0) {
1433 set_error(SPDY_INVALID_CONTROL_FRAME);
1434 break;
1437 SpdyStreamId associated_to_stream_id = kInvalidStream;
1438 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1439 DCHECK(successful_read);
1441 SpdyPriority priority = 0;
1442 successful_read = reader.ReadUInt8(&priority);
1443 DCHECK(successful_read);
1444 if (protocol_version() <= SPDY2) {
1445 priority = priority >> 6;
1446 } else {
1447 priority = priority >> 5;
1450 // Seek past unused byte; used to be credential slot in SPDY 3.
1451 reader.Seek(1);
1453 DCHECK(reader.IsDoneReading());
1454 if (debug_visitor_) {
1455 debug_visitor_->OnReceiveCompressedFrame(
1456 current_frame_stream_id_,
1457 current_frame_type_,
1458 current_frame_length_);
1460 visitor_->OnSynStream(
1461 current_frame_stream_id_,
1462 associated_to_stream_id,
1463 priority,
1464 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1465 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1467 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1468 break;
1469 case SETTINGS:
1470 if (protocol_version() > SPDY3 &&
1471 current_frame_flags_ & SETTINGS_FLAG_ACK) {
1472 visitor_->OnSettingsAck();
1473 CHANGE_STATE(SPDY_AUTO_RESET);
1474 } else {
1475 visitor_->OnSettings(current_frame_flags_ &
1476 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1477 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1479 break;
1480 case SYN_REPLY:
1481 case HEADERS:
1482 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1484 if (protocol_version() > SPDY3) {
1485 DCHECK_EQ(HEADERS, current_frame_type_);
1487 bool successful_read = true;
1488 if (protocol_version() <= SPDY3) {
1489 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1490 DCHECK(successful_read);
1492 if (current_frame_stream_id_ == 0) {
1493 set_error(SPDY_INVALID_CONTROL_FRAME);
1494 break;
1496 if (protocol_version() <= SPDY2) {
1497 // SPDY 2 had two unused bytes here. Seek past them.
1498 reader.Seek(2);
1500 if (protocol_version() > SPDY3 &&
1501 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1502 current_frame_type_ == HEADERS) {
1503 expect_continuation_ = current_frame_stream_id_;
1504 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1506 if (protocol_version() > SPDY3 &&
1507 current_frame_flags_ & HEADERS_FLAG_PADDED) {
1508 uint8 pad_payload_len = 0;
1509 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1510 successful_read = reader.ReadUInt8(&pad_payload_len);
1511 DCHECK(successful_read);
1512 remaining_padding_payload_length_ = pad_payload_len;
1514 const bool has_priority =
1515 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1516 SpdyPriority priority = 0;
1517 uint32 parent_stream_id = 0;
1518 bool exclusive = false;
1519 if (protocol_version() > SPDY3 && has_priority) {
1520 uint32 stream_dependency;
1521 successful_read = reader.ReadUInt32(&stream_dependency);
1522 DCHECK(successful_read);
1523 UnpackStreamDependencyValues(stream_dependency, &exclusive,
1524 &parent_stream_id);
1526 uint8 weight = 0;
1527 successful_read = reader.ReadUInt8(&weight);
1528 if (successful_read) {
1529 priority = MapWeightToPriority(weight);
1532 DCHECK(reader.IsDoneReading());
1533 if (debug_visitor_) {
1534 debug_visitor_->OnReceiveCompressedFrame(
1535 current_frame_stream_id_,
1536 current_frame_type_,
1537 current_frame_length_);
1539 if (current_frame_type_ == SYN_REPLY) {
1540 visitor_->OnSynReply(
1541 current_frame_stream_id_,
1542 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1543 } else {
1544 visitor_->OnHeaders(
1545 current_frame_stream_id_,
1546 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0, priority,
1547 parent_stream_id, exclusive,
1548 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1549 expect_continuation_ == 0);
1552 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1553 break;
1554 case PUSH_PROMISE:
1556 DCHECK_LT(SPDY3, protocol_version());
1557 if (current_frame_stream_id_ == 0) {
1558 set_error(SPDY_INVALID_CONTROL_FRAME);
1559 break;
1561 bool successful_read = true;
1562 if (protocol_version() > SPDY3 &&
1563 current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1564 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1565 uint8 pad_payload_len = 0;
1566 successful_read = reader.ReadUInt8(&pad_payload_len);
1567 DCHECK(successful_read);
1568 remaining_padding_payload_length_ = pad_payload_len;
1572 SpdyStreamId promised_stream_id = kInvalidStream;
1573 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1574 DCHECK(successful_read);
1575 DCHECK(reader.IsDoneReading());
1576 if (promised_stream_id == 0) {
1577 set_error(SPDY_INVALID_CONTROL_FRAME);
1578 break;
1580 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1581 expect_continuation_ = current_frame_stream_id_;
1583 if (debug_visitor_) {
1584 debug_visitor_->OnReceiveCompressedFrame(
1585 current_frame_stream_id_,
1586 current_frame_type_,
1587 current_frame_length_);
1589 visitor_->OnPushPromise(current_frame_stream_id_,
1590 promised_stream_id,
1591 (current_frame_flags_ &
1592 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1594 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1595 break;
1596 case CONTINUATION:
1598 // Check to make sure the stream id of the current frame is
1599 // the same as that of the preceding frame.
1600 // If we're at this point we should already know that
1601 // expect_continuation_ != 0, so this doubles as a check
1602 // that current_frame_stream_id != 0.
1603 if (current_frame_stream_id_ != expect_continuation_) {
1604 set_error(SPDY_INVALID_CONTROL_FRAME);
1605 break;
1607 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1608 expect_continuation_ = 0;
1610 if (debug_visitor_) {
1611 debug_visitor_->OnReceiveCompressedFrame(
1612 current_frame_stream_id_,
1613 current_frame_type_,
1614 current_frame_length_);
1616 visitor_->OnContinuation(current_frame_stream_id_,
1617 (current_frame_flags_ &
1618 HEADERS_FLAG_END_HEADERS) != 0);
1620 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1621 break;
1622 default:
1623 DCHECK(false);
1626 return original_len - len;
1629 // Does not buffer the control payload. Instead, either passes directly to the
1630 // visitor or decompresses and then passes directly to the visitor, via
1631 // IncrementallyDeliverControlFrameHeaderData() or
1632 // IncrementallyDecompressControlFrameHeaderData() respectively.
1633 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1634 size_t data_len,
1635 bool is_hpack_header_block) {
1636 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1638 bool processed_successfully = true;
1639 if (current_frame_type_ != SYN_STREAM &&
1640 current_frame_type_ != SYN_REPLY &&
1641 current_frame_type_ != HEADERS &&
1642 current_frame_type_ != PUSH_PROMISE &&
1643 current_frame_type_ != CONTINUATION) {
1644 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1646 size_t process_bytes = std::min(
1647 data_len, remaining_data_length_ - remaining_padding_payload_length_);
1648 if (is_hpack_header_block) {
1649 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1650 current_frame_stream_id_, data, process_bytes)) {
1651 // TODO(jgraettinger): Finer-grained HPACK error codes.
1652 set_error(SPDY_DECOMPRESS_FAILURE);
1653 processed_successfully = false;
1655 } else if (process_bytes > 0) {
1656 if (enable_compression_ && protocol_version() <= SPDY3) {
1657 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1658 current_frame_stream_id_, data, process_bytes);
1659 } else {
1660 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1661 current_frame_stream_id_, data, process_bytes);
1664 remaining_data_length_ -= process_bytes;
1666 // Handle the case that there is no futher data in this frame.
1667 if (remaining_data_length_ == remaining_padding_payload_length_ &&
1668 processed_successfully) {
1669 if (expect_continuation_ == 0) {
1670 if (is_hpack_header_block) {
1671 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1672 current_frame_stream_id_)) {
1673 set_error(SPDY_DECOMPRESS_FAILURE);
1674 processed_successfully = false;
1675 } else {
1676 // TODO(jgraettinger): To be removed with migration to
1677 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1678 // block, delivered via reentrant call to
1679 // ProcessControlFrameHeaderBlock().
1680 DeliverHpackBlockAsSpdy3Block();
1681 return process_bytes;
1683 } else {
1684 // The complete header block has been delivered. We send a zero-length
1685 // OnControlFrameHeaderData() to indicate this.
1686 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1689 if (processed_successfully) {
1690 CHANGE_STATE(SPDY_CONSUME_PADDING);
1694 // Handle error.
1695 if (!processed_successfully) {
1696 return data_len;
1699 // Return amount processed.
1700 return process_bytes;
1703 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1704 size_t data_len) {
1705 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1706 DCHECK_EQ(SETTINGS, current_frame_type_);
1707 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1708 size_t processed_bytes = 0;
1710 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
1712 // Loop over our incoming data.
1713 while (unprocessed_bytes > 0) {
1714 // Process up to one setting at a time.
1715 size_t processing = std::min(
1716 unprocessed_bytes,
1717 static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len));
1719 // Check if we have a complete setting in our input.
1720 if (processing == setting_size) {
1721 // Parse the setting directly out of the input without buffering.
1722 if (!ProcessSetting(data + processed_bytes)) {
1723 set_error(SPDY_INVALID_CONTROL_FRAME);
1724 return processed_bytes;
1726 } else {
1727 // Continue updating settings_scratch_.setting_buf.
1728 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1729 data + processed_bytes,
1730 processing);
1731 settings_scratch_.setting_buf_len += processing;
1733 // Check if we have a complete setting buffered.
1734 if (settings_scratch_.setting_buf_len == setting_size) {
1735 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1736 set_error(SPDY_INVALID_CONTROL_FRAME);
1737 return processed_bytes;
1739 // Reset settings_scratch_.setting_buf for our next setting.
1740 settings_scratch_.setting_buf_len = 0;
1744 // Iterate.
1745 unprocessed_bytes -= processing;
1746 processed_bytes += processing;
1749 // Check if we're done handling this SETTINGS frame.
1750 remaining_data_length_ -= processed_bytes;
1751 if (remaining_data_length_ == 0) {
1752 visitor_->OnSettingsEnd();
1753 CHANGE_STATE(SPDY_AUTO_RESET);
1756 return processed_bytes;
1759 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1760 DCHECK_LT(SPDY3, protocol_version());
1761 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1763 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
1764 if (block.empty()) {
1765 // Special-case this to make tests happy.
1766 ProcessControlFrameHeaderBlock(NULL, 0, false);
1767 return;
1769 SpdyFrameBuilder builder(
1770 GetSerializedLength(protocol_version(), &block),
1771 SPDY3);
1773 SerializeNameValueBlockWithoutCompression(&builder, block);
1774 scoped_ptr<SpdyFrame> frame(builder.take());
1776 // Preserve padding length, and reset it after the re-entrant call.
1777 size_t remaining_padding = remaining_padding_payload_length_;
1779 remaining_padding_payload_length_ = 0;
1780 remaining_data_length_ = frame->size();
1782 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1784 remaining_padding_payload_length_ = remaining_padding;
1785 remaining_data_length_ = remaining_padding;
1788 bool SpdyFramer::ProcessSetting(const char* data) {
1789 int id_field;
1790 SpdySettingsIds id;
1791 uint8 flags = 0;
1792 uint32 value;
1794 // Extract fields.
1795 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1796 if (protocol_version() <= SPDY3) {
1797 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1798 SettingsFlagsAndId id_and_flags =
1799 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
1800 id_field = id_and_flags.id();
1801 flags = id_and_flags.flags();
1802 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1803 } else {
1804 id_field = ntohs(*(reinterpret_cast<const uint16*>(data)));
1805 value = ntohl(*(reinterpret_cast<const uint32*>(data + 2)));
1808 // Validate id.
1809 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
1810 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1811 if (protocol_version() <= SPDY3) {
1812 return false;
1813 } else {
1814 // In HTTP2 we ignore unknown settings for extensibility.
1815 return true;
1818 id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
1820 if (protocol_version() <= SPDY3) {
1821 // Detect duplicates.
1822 if (id <= settings_scratch_.last_setting_id) {
1823 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1824 << " in " << display_protocol_ << " SETTINGS frame "
1825 << "(last setting id was "
1826 << settings_scratch_.last_setting_id << ").";
1827 return false;
1829 settings_scratch_.last_setting_id = id;
1831 // Validate flags.
1832 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1833 if ((flags & ~(kFlagsMask)) != 0) {
1834 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1835 << flags;
1836 return false;
1840 // Validation succeeded. Pass on to visitor.
1841 visitor_->OnSetting(id, flags, value);
1842 return true;
1845 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1846 size_t original_len = len;
1847 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1848 remaining_data_length_);
1849 remaining_data_length_ -= bytes_read;
1850 if (remaining_data_length_ == 0) {
1851 SpdyFrameReader reader(current_frame_buffer_.get(),
1852 current_frame_buffer_length_);
1853 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1855 // Use frame-specific handlers.
1856 switch (current_frame_type_) {
1857 case PING: {
1858 SpdyPingId id = 0;
1859 bool is_ack = protocol_version() > SPDY3 &&
1860 (current_frame_flags_ & PING_FLAG_ACK);
1861 bool successful_read = true;
1862 if (protocol_version() <= SPDY3) {
1863 uint32 id32 = 0;
1864 successful_read = reader.ReadUInt32(&id32);
1865 id = id32;
1866 } else {
1867 successful_read = reader.ReadUInt64(&id);
1869 DCHECK(successful_read);
1870 DCHECK(reader.IsDoneReading());
1871 visitor_->OnPing(id, is_ack);
1873 break;
1874 case WINDOW_UPDATE: {
1875 uint32 delta_window_size = 0;
1876 bool successful_read = true;
1877 if (protocol_version() <= SPDY3) {
1878 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1879 DCHECK(successful_read);
1881 successful_read = reader.ReadUInt32(&delta_window_size);
1882 DCHECK(successful_read);
1883 DCHECK(reader.IsDoneReading());
1884 visitor_->OnWindowUpdate(current_frame_stream_id_,
1885 delta_window_size);
1887 break;
1888 case BLOCKED: {
1889 DCHECK_LT(SPDY3, protocol_version());
1890 DCHECK(reader.IsDoneReading());
1891 visitor_->OnBlocked(current_frame_stream_id_);
1893 break;
1894 case PRIORITY: {
1895 DCHECK_LT(SPDY3, protocol_version());
1896 uint32 stream_dependency;
1897 uint32 parent_stream_id;
1898 bool exclusive;
1899 uint8 weight;
1900 bool successful_read = reader.ReadUInt32(&stream_dependency);
1901 DCHECK(successful_read);
1902 UnpackStreamDependencyValues(stream_dependency, &exclusive,
1903 &parent_stream_id);
1905 successful_read = reader.ReadUInt8(&weight);
1906 DCHECK(successful_read);
1907 DCHECK(reader.IsDoneReading());
1908 visitor_->OnPriority(
1909 current_frame_stream_id_, parent_stream_id, weight, exclusive);
1911 break;
1912 default:
1913 // Unreachable.
1914 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1917 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1919 return original_len - len;
1922 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1923 if (len == 0) {
1924 return 0;
1926 // Clamp to the actual remaining payload.
1927 if (len > remaining_data_length_) {
1928 len = remaining_data_length_;
1930 size_t original_len = len;
1932 // Check if we had already read enough bytes to parse the GOAWAY header.
1933 const size_t header_size = GetGoAwayMinimumSize();
1934 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1935 bool already_parsed_header = (unread_header_bytes == 0);
1936 if (!already_parsed_header) {
1937 // Buffer the new GOAWAY header bytes we got.
1938 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1940 // Do we have enough to parse the constant size GOAWAY header?
1941 if (current_frame_buffer_length_ == header_size) {
1942 // Parse out the last good stream id.
1943 SpdyFrameReader reader(current_frame_buffer_.get(),
1944 current_frame_buffer_length_);
1945 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1946 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1947 DCHECK(successful_read);
1949 // In SPDYv3 and up, frames also specify a status code - parse it out.
1950 SpdyGoAwayStatus status = GOAWAY_OK;
1951 if (protocol_version() >= SPDY3) {
1952 uint32 status_raw = GOAWAY_OK;
1953 successful_read = reader.ReadUInt32(&status_raw);
1954 DCHECK(successful_read);
1955 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1956 status_raw)) {
1957 status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
1958 status_raw);
1959 } else {
1960 if (protocol_version() > SPDY3) {
1961 // Treat unrecognized status codes as INTERNAL_ERROR as
1962 // recommended by the HTTP/2 spec.
1963 status = GOAWAY_INTERNAL_ERROR;
1967 // Finished parsing the GOAWAY header, call frame handler.
1968 visitor_->OnGoAway(current_frame_stream_id_, status);
1972 // Handle remaining data as opaque.
1973 bool processed_successfully = true;
1974 if (len > 0) {
1975 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1977 remaining_data_length_ -= original_len;
1978 if (!processed_successfully) {
1979 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1980 } else if (remaining_data_length_ == 0) {
1981 // Signal that there is not more opaque data.
1982 visitor_->OnGoAwayFrameData(NULL, 0);
1983 CHANGE_STATE(SPDY_AUTO_RESET);
1985 return original_len;
1988 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1989 if (len == 0) {
1990 return 0;
1992 // Clamp to the actual remaining payload.
1993 if (len > remaining_data_length_) {
1994 len = remaining_data_length_;
1996 size_t original_len = len;
1998 // Check if we had already read enough bytes to parse the fixed-length portion
1999 // of the RST_STREAM frame.
2000 const size_t header_size = GetRstStreamMinimumSize();
2001 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
2002 bool already_parsed_header = (unread_header_bytes == 0);
2003 if (!already_parsed_header) {
2004 // Buffer the new RST_STREAM header bytes we got.
2005 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
2007 // Do we have enough to parse the constant size RST_STREAM header?
2008 if (current_frame_buffer_length_ == header_size) {
2009 // Parse out the last good stream id.
2010 SpdyFrameReader reader(current_frame_buffer_.get(),
2011 current_frame_buffer_length_);
2012 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
2013 if (protocol_version() <= SPDY3) {
2014 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
2015 DCHECK(successful_read);
2018 SpdyRstStreamStatus status = RST_STREAM_INVALID;
2019 uint32 status_raw = status;
2020 bool successful_read = reader.ReadUInt32(&status_raw);
2021 DCHECK(successful_read);
2022 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
2023 status_raw)) {
2024 status =
2025 SpdyConstants::ParseRstStreamStatus(protocol_version(), status_raw);
2026 } else {
2027 if (protocol_version() > SPDY3) {
2028 // Treat unrecognized status codes as INTERNAL_ERROR as
2029 // recommended by the HTTP/2 spec.
2030 status = RST_STREAM_INTERNAL_ERROR;
2033 // Finished parsing the RST_STREAM header, call frame handler.
2034 visitor_->OnRstStream(current_frame_stream_id_, status);
2038 // Handle remaining data as opaque.
2039 bool processed_successfully = true;
2040 if (len > 0) {
2041 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
2043 remaining_data_length_ -= original_len;
2044 if (!processed_successfully) {
2045 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
2046 } else if (remaining_data_length_ == 0) {
2047 // Signal that there is not more opaque data.
2048 visitor_->OnRstStreamFrameData(NULL, 0);
2049 CHANGE_STATE(SPDY_AUTO_RESET);
2051 return original_len;
2054 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
2055 if (len == 0) {
2056 return 0;
2059 // Clamp to the actual remaining payload.
2060 len = std::min(len, remaining_data_length_);
2062 if (altsvc_scratch_.buffer.get() == nullptr) {
2063 altsvc_scratch_.buffer.reset(
2064 new char[current_frame_length_ - GetControlFrameHeaderSize()]);
2065 altsvc_scratch_.buffer_length = 0;
2067 memcpy(altsvc_scratch_.buffer.get() + altsvc_scratch_.buffer_length, data,
2068 len);
2069 altsvc_scratch_.buffer_length += len;
2070 remaining_data_length_ -= len;
2071 if (remaining_data_length_ > 0) {
2072 return len;
2075 SpdyFrameReader reader(altsvc_scratch_.buffer.get(),
2076 altsvc_scratch_.buffer_length);
2077 StringPiece origin;
2078 bool successful_read = reader.ReadStringPiece16(&origin);
2079 if (!successful_read) {
2080 set_error(SPDY_INVALID_CONTROL_FRAME);
2081 return 0;
2083 StringPiece value(altsvc_scratch_.buffer.get() + reader.GetBytesConsumed(),
2084 altsvc_scratch_.buffer_length - reader.GetBytesConsumed());
2086 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
2087 bool success =
2088 SpdyAltSvcWireFormat::ParseHeaderFieldValue(value, &altsvc_vector);
2089 if (!success) {
2090 set_error(SPDY_INVALID_CONTROL_FRAME);
2091 return 0;
2094 visitor_->OnAltSvc(current_frame_stream_id_, origin, altsvc_vector);
2095 CHANGE_STATE(SPDY_AUTO_RESET);
2096 return len;
2099 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) {
2100 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_);
2101 DCHECK_EQ(0u, remaining_padding_payload_length_);
2102 DCHECK_EQ(DATA, current_frame_type_);
2104 size_t original_len = len;
2105 if (current_frame_flags_ & DATA_FLAG_PADDED) {
2106 if (len != 0) {
2107 if (remaining_data_length_ < kPadLengthFieldSize) {
2108 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2109 return 0;
2112 static_assert(kPadLengthFieldSize == 1,
2113 "Unexpected pad length field size.");
2114 remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data);
2115 ++data;
2116 --len;
2117 --remaining_data_length_;
2118 visitor_->OnStreamPadding(current_frame_stream_id_, kPadLengthFieldSize);
2119 } else {
2120 // We don't have the data available for parsing the pad length field. Keep
2121 // waiting.
2122 return 0;
2126 if (remaining_padding_payload_length_ > remaining_data_length_) {
2127 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2128 return 0;
2130 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2131 return original_len - len;
2134 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
2135 DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
2137 size_t original_len = len;
2138 if (remaining_padding_payload_length_ > 0) {
2139 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
2140 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2141 if (current_frame_type_ == DATA && amount_to_discard > 0) {
2142 DCHECK_LE(HTTP2, protocol_version());
2143 visitor_->OnStreamPadding(current_frame_stream_id_, amount_to_discard);
2145 data += amount_to_discard;
2146 len -= amount_to_discard;
2147 remaining_padding_payload_length_ -= amount_to_discard;
2148 remaining_data_length_ -= amount_to_discard;
2151 if (remaining_data_length_ == 0) {
2152 // If the FIN flag is set, or this ends a header block which set FIN,
2153 // inform the visitor of EOF via a 0-length data frame.
2154 if (expect_continuation_ == 0 &&
2155 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2156 end_stream_when_done_)) {
2157 end_stream_when_done_ = false;
2158 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
2160 CHANGE_STATE(SPDY_AUTO_RESET);
2162 return original_len - len;
2165 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
2166 size_t original_len = len;
2167 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
2168 size_t amount_to_forward = std::min(
2169 remaining_data_length_ - remaining_padding_payload_length_, len);
2170 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
2171 // Only inform the visitor if there is data.
2172 if (amount_to_forward) {
2173 visitor_->OnStreamFrameData(
2174 current_frame_stream_id_, data, amount_to_forward, false);
2177 data += amount_to_forward;
2178 len -= amount_to_forward;
2179 remaining_data_length_ -= amount_to_forward;
2182 if (remaining_data_length_ == remaining_padding_payload_length_) {
2183 CHANGE_STATE(SPDY_CONSUME_PADDING);
2185 return original_len - len;
2188 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2189 size_t len) {
2190 size_t original_len = len;
2191 if (remaining_data_length_ > 0) {
2192 size_t amount_to_ignore = std::min(remaining_data_length_, len);
2193 len -= amount_to_ignore;
2194 remaining_data_length_ -= amount_to_ignore;
2197 if (remaining_data_length_ == 0) {
2198 CHANGE_STATE(SPDY_AUTO_RESET);
2200 return original_len - len;
2203 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
2204 size_t header_length,
2205 SpdyHeaderBlock* block) const {
2206 SpdyFrameReader reader(header_data, header_length);
2208 // Read number of headers.
2209 uint32 num_headers;
2210 if (protocol_version() <= SPDY2) {
2211 uint16 temp;
2212 if (!reader.ReadUInt16(&temp)) {
2213 DVLOG(1) << "Unable to read number of headers.";
2214 return 0;
2216 num_headers = temp;
2217 } else {
2218 if (!reader.ReadUInt32(&num_headers)) {
2219 DVLOG(1) << "Unable to read number of headers.";
2220 return 0;
2224 // Read each header.
2225 for (uint32 index = 0; index < num_headers; ++index) {
2226 base::StringPiece temp;
2228 // Read header name.
2229 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2230 : !reader.ReadStringPiece32(&temp)) {
2231 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2232 << num_headers << ").";
2233 return 0;
2235 std::string name = temp.as_string();
2237 // Read header value.
2238 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2239 : !reader.ReadStringPiece32(&temp)) {
2240 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2241 << num_headers << ").";
2242 return 0;
2244 std::string value = temp.as_string();
2246 // Ensure no duplicates.
2247 if (block->find(name) != block->end()) {
2248 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2249 << num_headers << ").";
2250 return 0;
2253 // Store header.
2254 (*block)[name] = value;
2256 return reader.GetBytesConsumed();
2259 SpdySerializedFrame* SpdyFramer::SerializeData(
2260 const SpdyDataIR& data_ir) const {
2261 uint8 flags = DATA_FLAG_NONE;
2262 if (data_ir.fin()) {
2263 flags = DATA_FLAG_FIN;
2266 if (protocol_version() > SPDY3) {
2267 int num_padding_fields = 0;
2268 if (data_ir.padded()) {
2269 flags |= DATA_FLAG_PADDED;
2270 ++num_padding_fields;
2273 const size_t size_with_padding = num_padding_fields +
2274 data_ir.data().length() + data_ir.padding_payload_len() +
2275 GetDataFrameMinimumSize();
2276 SpdyFrameBuilder builder(size_with_padding, protocol_version());
2277 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2278 if (data_ir.padded()) {
2279 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2281 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2282 if (data_ir.padding_payload_len() > 0) {
2283 string padding(data_ir.padding_payload_len(), 0);
2284 builder.WriteBytes(padding.data(), padding.length());
2286 DCHECK_EQ(size_with_padding, builder.length());
2287 return builder.take();
2288 } else {
2289 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
2290 SpdyFrameBuilder builder(size, protocol_version());
2291 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2292 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2293 DCHECK_EQ(size, builder.length());
2294 return builder.take();
2298 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2299 const SpdyDataIR& data_ir) const {
2300 uint8 flags = DATA_FLAG_NONE;
2301 if (data_ir.fin()) {
2302 flags = DATA_FLAG_FIN;
2305 size_t frame_size = GetDataFrameMinimumSize();
2306 size_t num_padding_fields = 0;
2307 if (protocol_version() > SPDY3) {
2308 if (data_ir.padded()) {
2309 flags |= DATA_FLAG_PADDED;
2310 ++num_padding_fields;
2312 frame_size += num_padding_fields;
2315 SpdyFrameBuilder builder(frame_size, protocol_version());
2316 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2317 if (protocol_version() > SPDY3) {
2318 if (data_ir.padded()) {
2319 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2321 builder.OverwriteLength(*this, num_padding_fields +
2322 data_ir.data().length() + data_ir.padding_payload_len());
2323 } else {
2324 builder.OverwriteLength(*this, data_ir.data().length());
2326 DCHECK_EQ(frame_size, builder.length());
2327 return builder.take();
2330 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
2331 const SpdySynStreamIR& syn_stream) {
2332 DCHECK_GE(SPDY3, protocol_version());
2333 uint8 flags = 0;
2334 if (syn_stream.fin()) {
2335 flags |= CONTROL_FLAG_FIN;
2337 if (syn_stream.unidirectional()) {
2338 // TODO(hkhalil): invalid for HTTP2.
2339 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
2342 // Sanitize priority.
2343 uint8 priority = syn_stream.priority();
2344 if (priority > GetLowestPriority()) {
2345 DLOG(DFATAL) << "Priority out-of-bounds.";
2346 priority = GetLowestPriority();
2349 // The size of this frame, including variable-length name-value block.
2350 size_t size = GetSynStreamMinimumSize() +
2351 GetSerializedLength(syn_stream.name_value_block());
2353 SpdyFrameBuilder builder(size, protocol_version());
2354 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2355 builder.WriteUInt32(syn_stream.stream_id());
2356 builder.WriteUInt32(syn_stream.associated_to_stream_id());
2357 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2358 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
2359 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2360 SerializeNameValueBlock(&builder, syn_stream);
2362 if (debug_visitor_) {
2363 const size_t payload_len =
2364 GetSerializedLength(protocol_version(),
2365 &(syn_stream.name_value_block()));
2366 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
2367 SYN_STREAM,
2368 payload_len,
2369 builder.length());
2372 return builder.take();
2375 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
2376 const SpdySynReplyIR& syn_reply) {
2377 DCHECK_GE(SPDY3, protocol_version());
2378 uint8 flags = 0;
2379 if (syn_reply.fin()) {
2380 flags |= CONTROL_FLAG_FIN;
2383 // The size of this frame, including variable-length name-value block.
2384 const size_t size = GetSynReplyMinimumSize() +
2385 GetSerializedLength(syn_reply.name_value_block());
2387 SpdyFrameBuilder builder(size, protocol_version());
2388 if (protocol_version() <= SPDY3) {
2389 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
2390 builder.WriteUInt32(syn_reply.stream_id());
2391 } else {
2392 builder.BeginNewFrame(*this,
2393 HEADERS,
2394 flags,
2395 syn_reply.stream_id());
2397 if (protocol_version() < SPDY3) {
2398 builder.WriteUInt16(0); // Unused.
2400 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2401 SerializeNameValueBlock(&builder, syn_reply);
2403 if (debug_visitor_) {
2404 const size_t payload_len = GetSerializedLength(
2405 protocol_version(), &(syn_reply.name_value_block()));
2406 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
2407 SYN_REPLY,
2408 payload_len,
2409 builder.length());
2412 return builder.take();
2415 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
2416 const SpdyRstStreamIR& rst_stream) const {
2417 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2418 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2419 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2420 // commented but left in place to simplify future patching.
2421 // Compute the output buffer size, taking opaque data into account.
2422 size_t expected_length = GetRstStreamMinimumSize();
2423 if (protocol_version() > SPDY3) {
2424 expected_length += rst_stream.description().size();
2426 SpdyFrameBuilder builder(expected_length, protocol_version());
2428 // Serialize the RST_STREAM frame.
2429 if (protocol_version() <= SPDY3) {
2430 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
2431 builder.WriteUInt32(rst_stream.stream_id());
2432 } else {
2433 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
2436 builder.WriteUInt32(SpdyConstants::SerializeRstStreamStatus(
2437 protocol_version(), rst_stream.status()));
2439 // In HTTP2 and up, RST_STREAM frames may also specify opaque data.
2440 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
2441 builder.WriteBytes(rst_stream.description().data(),
2442 rst_stream.description().size());
2445 DCHECK_EQ(expected_length, builder.length());
2446 return builder.take();
2449 SpdySerializedFrame* SpdyFramer::SerializeSettings(
2450 const SpdySettingsIR& settings) const {
2451 uint8 flags = 0;
2453 if (protocol_version() <= SPDY3) {
2454 if (settings.clear_settings()) {
2455 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2457 } else {
2458 if (settings.is_ack()) {
2459 flags |= SETTINGS_FLAG_ACK;
2462 const SpdySettingsIR::ValueMap* values = &(settings.values());
2464 size_t setting_size = SpdyConstants::GetSettingSize(protocol_version());
2465 // Size, in bytes, of this SETTINGS frame.
2466 const size_t size = GetSettingsMinimumSize() +
2467 (values->size() * setting_size);
2468 SpdyFrameBuilder builder(size, protocol_version());
2469 if (protocol_version() <= SPDY3) {
2470 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
2471 } else {
2472 builder.BeginNewFrame(*this, SETTINGS, flags, 0);
2475 // If this is an ACK, payload should be empty.
2476 if (protocol_version() > SPDY3 && settings.is_ack()) {
2477 return builder.take();
2480 if (protocol_version() <= SPDY3) {
2481 builder.WriteUInt32(values->size());
2483 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2484 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
2485 it != values->end();
2486 ++it) {
2487 int setting_id =
2488 SpdyConstants::SerializeSettingId(protocol_version(), it->first);
2489 DCHECK_GE(setting_id, 0);
2490 if (protocol_version() <= SPDY3) {
2491 uint8 setting_flags = 0;
2492 if (it->second.persist_value) {
2493 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2495 if (it->second.persisted) {
2496 setting_flags |= SETTINGS_FLAG_PERSISTED;
2498 SettingsFlagsAndId flags_and_id(setting_flags, setting_id);
2499 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2500 builder.WriteBytes(&id_and_flags_wire, 4);
2501 } else {
2502 builder.WriteUInt16(static_cast<uint16>(setting_id));
2504 builder.WriteUInt32(it->second.value);
2506 DCHECK_EQ(size, builder.length());
2507 return builder.take();
2510 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
2511 SpdyFrameBuilder builder(GetPingSize(), protocol_version());
2512 if (protocol_version() <= SPDY3) {
2513 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
2514 builder.WriteUInt32(static_cast<uint32>(ping.id()));
2515 } else {
2516 uint8 flags = 0;
2517 if (ping.is_ack()) {
2518 flags |= PING_FLAG_ACK;
2520 builder.BeginNewFrame(*this, PING, flags, 0);
2521 builder.WriteUInt64(ping.id());
2523 DCHECK_EQ(GetPingSize(), builder.length());
2524 return builder.take();
2527 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
2528 const SpdyGoAwayIR& goaway) const {
2530 // Compute the output buffer size, take opaque data into account.
2531 size_t expected_length = GetGoAwayMinimumSize();
2532 if (protocol_version() > SPDY3) {
2533 expected_length += goaway.description().size();
2535 SpdyFrameBuilder builder(expected_length, protocol_version());
2537 // Serialize the GOAWAY frame.
2538 if (protocol_version() <= SPDY3) {
2539 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
2540 } else {
2541 builder.BeginNewFrame(*this, GOAWAY, 0, 0);
2544 // GOAWAY frames specify the last good stream id for all SPDY versions.
2545 builder.WriteUInt32(goaway.last_good_stream_id());
2547 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2548 if (protocol_version() >= SPDY3) {
2549 // TODO(jgraettinger): Merge back to server-side.
2550 builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2551 goaway.status()));
2554 // In HTTP2 and up, GOAWAY frames may also specify opaque data.
2555 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
2556 builder.WriteBytes(goaway.description().data(),
2557 goaway.description().size());
2560 DCHECK_EQ(expected_length, builder.length());
2561 return builder.take();
2564 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2565 const SpdyHeadersIR& headers) {
2566 uint8 flags = 0;
2567 if (headers.fin()) {
2568 flags |= CONTROL_FLAG_FIN;
2570 if (protocol_version() > SPDY3) {
2571 // This will get overwritten if we overflow into a CONTINUATION frame.
2572 flags |= HEADERS_FLAG_END_HEADERS;
2573 if (headers.has_priority()) {
2574 flags |= HEADERS_FLAG_PRIORITY;
2576 if (headers.padded()) {
2577 flags |= HEADERS_FLAG_PADDED;
2581 // The size of this frame, including padding (if there is any)
2582 // and variable-length name-value block.
2583 size_t size = GetHeadersMinimumSize();
2585 if (protocol_version() > SPDY3 && headers.padded()) {
2586 size += kPadLengthFieldSize;
2587 size += headers.padding_payload_len();
2590 SpdyPriority priority = static_cast<SpdyPriority>(headers.priority());
2591 if (headers.has_priority()) {
2592 if (headers.priority() > GetLowestPriority()) {
2593 DLOG(DFATAL) << "Priority out-of-bounds.";
2594 priority = GetLowestPriority();
2596 size += 5;
2599 string hpack_encoding;
2600 if (protocol_version() > SPDY3) {
2601 if (enable_compression_) {
2602 GetHpackEncoder()->EncodeHeaderSet(
2603 headers.name_value_block(), &hpack_encoding);
2604 } else {
2605 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2606 headers.name_value_block(), &hpack_encoding);
2608 size += hpack_encoding.size();
2609 if (size > kMaxControlFrameSize) {
2610 size += GetNumberRequiredContinuationFrames(size) *
2611 GetContinuationMinimumSize();
2612 flags &= ~HEADERS_FLAG_END_HEADERS;
2614 } else {
2615 size += GetSerializedLength(headers.name_value_block());
2618 SpdyFrameBuilder builder(size, protocol_version());
2619 if (protocol_version() <= SPDY3) {
2620 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2621 builder.WriteUInt32(headers.stream_id());
2622 } else {
2623 builder.BeginNewFrame(*this,
2624 HEADERS,
2625 flags,
2626 headers.stream_id());
2628 if (protocol_version() <= SPDY2) {
2629 builder.WriteUInt16(0); // Unused.
2631 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2633 if (protocol_version() > SPDY3) {
2634 int padding_payload_len = 0;
2635 if (headers.padded()) {
2636 builder.WriteUInt8(headers.padding_payload_len());
2637 padding_payload_len = headers.padding_payload_len();
2639 if (headers.has_priority()) {
2640 builder.WriteUInt32(PackStreamDependencyValues(
2641 headers.exclusive(), headers.parent_stream_id()));
2642 builder.WriteUInt8(MapPriorityToWeight(priority));
2644 WritePayloadWithContinuation(&builder,
2645 hpack_encoding,
2646 headers.stream_id(),
2647 HEADERS,
2648 padding_payload_len);
2649 } else {
2650 SerializeNameValueBlock(&builder, headers);
2653 if (debug_visitor_) {
2654 // HTTP2 uses HPACK for header compression. However, continue to
2655 // use GetSerializedLength() for an apples-to-apples comparision of
2656 // compression performance between HPACK and SPDY w/ deflate.
2657 const size_t payload_len =
2658 GetSerializedLength(protocol_version(),
2659 &(headers.name_value_block()));
2660 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2661 HEADERS,
2662 payload_len,
2663 builder.length());
2666 return builder.take();
2669 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2670 const SpdyWindowUpdateIR& window_update) const {
2671 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
2672 if (protocol_version() <= SPDY3) {
2673 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2674 builder.WriteUInt32(window_update.stream_id());
2675 } else {
2676 builder.BeginNewFrame(*this,
2677 WINDOW_UPDATE,
2678 kNoFlags,
2679 window_update.stream_id());
2681 builder.WriteUInt32(window_update.delta());
2682 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2683 return builder.take();
2686 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
2687 DCHECK_LT(SPDY3, protocol_version());
2688 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
2689 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
2690 return builder.take();
2693 SpdyFrame* SpdyFramer::SerializePushPromise(
2694 const SpdyPushPromiseIR& push_promise) {
2695 DCHECK_LT(SPDY3, protocol_version());
2696 uint8 flags = 0;
2697 // This will get overwritten if we overflow into a CONTINUATION frame.
2698 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2699 // The size of this frame, including variable-length name-value block.
2700 size_t size = GetPushPromiseMinimumSize();
2702 if (push_promise.padded()) {
2703 flags |= PUSH_PROMISE_FLAG_PADDED;
2704 size += kPadLengthFieldSize;
2705 size += push_promise.padding_payload_len();
2708 string hpack_encoding;
2709 if (enable_compression_) {
2710 GetHpackEncoder()->EncodeHeaderSet(
2711 push_promise.name_value_block(), &hpack_encoding);
2712 } else {
2713 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2714 push_promise.name_value_block(), &hpack_encoding);
2716 size += hpack_encoding.size();
2717 if (size > kMaxControlFrameSize) {
2718 size += GetNumberRequiredContinuationFrames(size) *
2719 GetContinuationMinimumSize();
2720 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2723 SpdyFrameBuilder builder(size, protocol_version());
2724 builder.BeginNewFrame(*this,
2725 PUSH_PROMISE,
2726 flags,
2727 push_promise.stream_id());
2728 int padding_payload_len = 0;
2729 if (push_promise.padded()) {
2730 builder.WriteUInt8(push_promise.padding_payload_len());
2731 builder.WriteUInt32(push_promise.promised_stream_id());
2732 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize,
2733 builder.length());
2735 padding_payload_len = push_promise.padding_payload_len();
2736 } else {
2737 builder.WriteUInt32(push_promise.promised_stream_id());
2738 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2741 WritePayloadWithContinuation(&builder,
2742 hpack_encoding,
2743 push_promise.stream_id(),
2744 PUSH_PROMISE,
2745 padding_payload_len);
2747 if (debug_visitor_) {
2748 // HTTP2 uses HPACK for header compression. However, continue to
2749 // use GetSerializedLength() for an apples-to-apples comparision of
2750 // compression performance between HPACK and SPDY w/ deflate.
2751 const size_t payload_len =
2752 GetSerializedLength(protocol_version(),
2753 &(push_promise.name_value_block()));
2754 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2755 PUSH_PROMISE,
2756 payload_len,
2757 builder.length());
2760 return builder.take();
2763 // TODO(jgraettinger): This implementation is incorrect. The continuation
2764 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2765 // new one. Figure out whether it makes sense to keep SerializeContinuation().
2766 SpdyFrame* SpdyFramer::SerializeContinuation(
2767 const SpdyContinuationIR& continuation) {
2768 CHECK_LT(SPDY3, protocol_version());
2769 uint8 flags = 0;
2770 if (continuation.end_headers()) {
2771 flags |= HEADERS_FLAG_END_HEADERS;
2774 // The size of this frame, including variable-length name-value block.
2775 size_t size = GetContinuationMinimumSize();
2776 string hpack_encoding;
2777 if (enable_compression_) {
2778 GetHpackEncoder()->EncodeHeaderSet(
2779 continuation.name_value_block(), &hpack_encoding);
2780 } else {
2781 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2782 continuation.name_value_block(), &hpack_encoding);
2784 size += hpack_encoding.size();
2786 SpdyFrameBuilder builder(size, protocol_version());
2787 builder.BeginNewFrame(*this, CONTINUATION, flags,
2788 continuation.stream_id());
2789 DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2791 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2792 return builder.take();
2795 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
2796 DCHECK_LT(SPDY3, protocol_version());
2798 size_t size = GetAltSvcMinimumSize();
2799 size += altsvc_ir.origin().length();
2800 string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
2801 altsvc_ir.altsvc_vector());
2802 size += value.length();
2804 SpdyFrameBuilder builder(size, protocol_version());
2805 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id());
2807 builder.WriteUInt16(altsvc_ir.origin().length());
2808 builder.WriteBytes(altsvc_ir.origin().data(), altsvc_ir.origin().length());
2809 builder.WriteBytes(value.data(), value.length());
2810 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2811 return builder.take();
2814 SpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) const {
2815 DCHECK_LT(SPDY3, protocol_version());
2816 size_t size = GetPrioritySize();
2818 SpdyFrameBuilder builder(size, protocol_version());
2819 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id());
2821 builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(),
2822 priority.parent_stream_id()));
2823 builder.WriteUInt8(priority.weight());
2824 DCHECK_EQ(GetPrioritySize(), builder.length());
2825 return builder.take();
2828 namespace {
2830 class FrameSerializationVisitor : public SpdyFrameVisitor {
2831 public:
2832 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2833 ~FrameSerializationVisitor() override {}
2835 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2837 void VisitData(const SpdyDataIR& data) override {
2838 frame_.reset(framer_->SerializeData(data));
2840 void VisitSynStream(const SpdySynStreamIR& syn_stream) override {
2841 frame_.reset(framer_->SerializeSynStream(syn_stream));
2843 void VisitSynReply(const SpdySynReplyIR& syn_reply) override {
2844 frame_.reset(framer_->SerializeSynReply(syn_reply));
2846 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
2847 frame_.reset(framer_->SerializeRstStream(rst_stream));
2849 void VisitSettings(const SpdySettingsIR& settings) override {
2850 frame_.reset(framer_->SerializeSettings(settings));
2852 void VisitPing(const SpdyPingIR& ping) override {
2853 frame_.reset(framer_->SerializePing(ping));
2855 void VisitGoAway(const SpdyGoAwayIR& goaway) override {
2856 frame_.reset(framer_->SerializeGoAway(goaway));
2858 void VisitHeaders(const SpdyHeadersIR& headers) override {
2859 frame_.reset(framer_->SerializeHeaders(headers));
2861 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
2862 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2864 void VisitBlocked(const SpdyBlockedIR& blocked) override {
2865 frame_.reset(framer_->SerializeBlocked(blocked));
2867 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
2868 frame_.reset(framer_->SerializePushPromise(push_promise));
2870 void VisitContinuation(const SpdyContinuationIR& continuation) override {
2871 frame_.reset(framer_->SerializeContinuation(continuation));
2873 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override {
2874 frame_.reset(framer_->SerializeAltSvc(altsvc));
2876 void VisitPriority(const SpdyPriorityIR& priority) override {
2877 frame_.reset(framer_->SerializePriority(priority));
2880 private:
2881 SpdyFramer* framer_;
2882 scoped_ptr<SpdySerializedFrame> frame_;
2885 } // namespace
2887 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2888 FrameSerializationVisitor visitor(this);
2889 frame.Visit(&visitor);
2890 return visitor.ReleaseSerializedFrame();
2893 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2894 CHECK_GE(SPDY3, protocol_version());
2895 const size_t uncompressed_length =
2896 GetSerializedLength(protocol_version(), &headers);
2897 if (!enable_compression_) {
2898 return uncompressed_length;
2900 z_stream* compressor = GetHeaderCompressor();
2901 // Since we'll be performing lots of flushes when compressing the data,
2902 // zlib's lower bounds may be insufficient.
2903 return 2 * deflateBound(compressor, uncompressed_length);
2906 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2907 DCHECK_GT(protocol_version(), SPDY3);
2908 DCHECK_GT(size, kMaxControlFrameSize);
2909 size_t overflow = size - kMaxControlFrameSize;
2910 size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
2911 // This is ceiling(overflow/payload_size) using integer arithmetics.
2912 return (overflow - 1) / payload_size + 1;
2915 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2916 const string& hpack_encoding,
2917 SpdyStreamId stream_id,
2918 SpdyFrameType type,
2919 int padding_payload_len) {
2920 uint8 end_flag = 0;
2921 uint8 flags = 0;
2922 if (type == HEADERS) {
2923 end_flag = HEADERS_FLAG_END_HEADERS;
2924 } else if (type == PUSH_PROMISE) {
2925 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2926 } else {
2927 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2928 << FrameTypeToString(type);
2931 // Write all the padding payload and as much of the data payload as possible
2932 // into the initial frame.
2933 size_t bytes_remaining = 0;
2934 bytes_remaining =
2935 hpack_encoding.size() -
2936 std::min(hpack_encoding.size(),
2937 kMaxControlFrameSize - builder->length() - padding_payload_len);
2938 builder->WriteBytes(&hpack_encoding[0],
2939 hpack_encoding.size() - bytes_remaining);
2940 if (padding_payload_len > 0) {
2941 string padding = string(padding_payload_len, 0);
2942 builder->WriteBytes(padding.data(), padding.length());
2944 if (bytes_remaining > 0) {
2945 builder->OverwriteLength(
2946 *this, kMaxControlFrameSize - GetControlFrameHeaderSize());
2949 // Tack on CONTINUATION frames for the overflow.
2950 while (bytes_remaining > 0) {
2951 size_t bytes_to_write = std::min(
2952 bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize());
2953 // Write CONTINUATION frame prefix.
2954 if (bytes_remaining == bytes_to_write) {
2955 flags |= end_flag;
2957 builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id);
2958 // Write payload fragment.
2959 builder->WriteBytes(
2960 &hpack_encoding[hpack_encoding.size() - bytes_remaining],
2961 bytes_to_write);
2962 bytes_remaining -= bytes_to_write;
2966 // The following compression setting are based on Brian Olson's analysis. See
2967 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2968 // for more details.
2969 #if defined(USE_SYSTEM_ZLIB)
2970 // System zlib is not expected to have workaround for http://crbug.com/139744,
2971 // so disable compression in that case.
2972 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2973 static const int kCompressorLevel = 0;
2974 #else // !defined(USE_SYSTEM_ZLIB)
2975 static const int kCompressorLevel = 9;
2976 #endif // !defined(USE_SYSTEM_ZLIB)
2977 static const int kCompressorWindowSizeInBits = 11;
2978 static const int kCompressorMemLevel = 1;
2980 z_stream* SpdyFramer::GetHeaderCompressor() {
2981 if (header_compressor_.get())
2982 return header_compressor_.get(); // Already initialized.
2984 header_compressor_.reset(new z_stream);
2985 memset(header_compressor_.get(), 0, sizeof(z_stream));
2987 int success = deflateInit2(header_compressor_.get(),
2988 kCompressorLevel,
2989 Z_DEFLATED,
2990 kCompressorWindowSizeInBits,
2991 kCompressorMemLevel,
2992 Z_DEFAULT_STRATEGY);
2993 if (success == Z_OK) {
2994 const char* dictionary = (protocol_version() <= SPDY2) ?
2995 kV2Dictionary : kV3Dictionary;
2996 const int dictionary_size = (protocol_version() <= SPDY2) ?
2997 kV2DictionarySize : kV3DictionarySize;
2998 success = deflateSetDictionary(header_compressor_.get(),
2999 reinterpret_cast<const Bytef*>(dictionary),
3000 dictionary_size);
3002 if (success != Z_OK) {
3003 LOG(WARNING) << "deflateSetDictionary failure: " << success;
3004 header_compressor_.reset(NULL);
3005 return NULL;
3007 return header_compressor_.get();
3010 z_stream* SpdyFramer::GetHeaderDecompressor() {
3011 if (header_decompressor_.get())
3012 return header_decompressor_.get(); // Already initialized.
3014 header_decompressor_.reset(new z_stream);
3015 memset(header_decompressor_.get(), 0, sizeof(z_stream));
3017 int success = inflateInit(header_decompressor_.get());
3018 if (success != Z_OK) {
3019 LOG(WARNING) << "inflateInit failure: " << success;
3020 header_decompressor_.reset(NULL);
3021 return NULL;
3023 return header_decompressor_.get();
3026 HpackEncoder* SpdyFramer::GetHpackEncoder() {
3027 DCHECK_LT(SPDY3, protocol_version());
3028 if (hpack_encoder_.get() == nullptr) {
3029 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3031 return hpack_encoder_.get();
3034 HpackDecoder* SpdyFramer::GetHpackDecoder() {
3035 DCHECK_LT(SPDY3, protocol_version());
3036 if (hpack_decoder_.get() == nullptr) {
3037 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3039 return hpack_decoder_.get();
3042 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3043 const float kSteps = 255.9f / 7.f;
3044 return static_cast<uint8>(kSteps * (7.f - priority));
3047 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3048 const float kSteps = 255.9f / 7.f;
3049 return static_cast<SpdyPriority>(7.f - weight / kSteps);
3052 // Incrementally decompress the control frame's header block, feeding the
3053 // result to the visitor in chunks. Continue this until the visitor
3054 // indicates that it cannot process any more data, or (more commonly) we
3055 // run out of data to deliver.
3056 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3057 SpdyStreamId stream_id,
3058 const char* data,
3059 size_t len) {
3060 // Get a decompressor or set error.
3061 z_stream* decomp = GetHeaderDecompressor();
3062 if (decomp == NULL) {
3063 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
3064 set_error(SPDY_DECOMPRESS_FAILURE);
3065 return false;
3068 bool processed_successfully = true;
3069 char buffer[kHeaderDataChunkMaxSize];
3071 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
3072 decomp->avail_in = len;
3073 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3074 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3075 // reached this method successfully, stream_id should be nonzero.
3076 DCHECK_LT(0u, stream_id);
3077 while (decomp->avail_in > 0 && processed_successfully) {
3078 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
3079 decomp->avail_out = arraysize(buffer);
3081 int rv = inflate(decomp, Z_SYNC_FLUSH);
3082 if (rv == Z_NEED_DICT) {
3083 const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
3084 : kV3Dictionary;
3085 const int dictionary_size = (protocol_version() <= SPDY2) ?
3086 kV2DictionarySize : kV3DictionarySize;
3087 const DictionaryIds& ids = g_dictionary_ids.Get();
3088 const uLong dictionary_id = (protocol_version() <= SPDY2) ?
3089 ids.v2_dictionary_id : ids.v3_dictionary_id;
3090 // Need to try again with the right dictionary.
3091 if (decomp->adler == dictionary_id) {
3092 rv = inflateSetDictionary(decomp,
3093 reinterpret_cast<const Bytef*>(dictionary),
3094 dictionary_size);
3095 if (rv == Z_OK)
3096 rv = inflate(decomp, Z_SYNC_FLUSH);
3100 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3101 // without producing any output. The input is consumed and
3102 // buffered internally by zlib so we can detect this condition by
3103 // checking if avail_in is 0 after the call to inflate.
3104 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
3105 if ((rv == Z_OK) || input_exhausted) {
3106 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
3107 if (decompressed_len > 0) {
3108 processed_successfully = visitor_->OnControlFrameHeaderData(
3109 stream_id, buffer, decompressed_len);
3111 if (!processed_successfully) {
3112 // Assume that the problem was the header block was too large for the
3113 // visitor.
3114 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3116 } else {
3117 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
3118 set_error(SPDY_DECOMPRESS_FAILURE);
3119 processed_successfully = false;
3122 return processed_successfully;
3125 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3126 SpdyStreamId stream_id, const char* data, size_t len) {
3127 bool read_successfully = true;
3128 while (read_successfully && len > 0) {
3129 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
3130 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
3131 bytes_to_deliver);
3132 data += bytes_to_deliver;
3133 len -= bytes_to_deliver;
3134 if (!read_successfully) {
3135 // Assume that the problem was the header block was too large for the
3136 // visitor.
3137 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3140 return read_successfully;
3143 void SpdyFramer::UpdateHeaderTableSizeSetting(uint32 value) {
3144 header_table_size_bound_ = value;
3145 GetHpackEncoder()->ApplyHeaderTableSizeSetting(value);
3146 GetHpackDecoder()->ApplyHeaderTableSizeSetting(value);
3149 // Return size bound of the header compression table.
3150 size_t SpdyFramer::header_table_size_bound() const {
3151 return header_table_size_bound_;
3154 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3155 SpdyFrameBuilder* builder,
3156 const SpdyNameValueBlock& name_value_block) const {
3157 // Serialize number of headers.
3158 if (protocol_version() <= SPDY2) {
3159 builder->WriteUInt16(static_cast<uint16>(name_value_block.size()));
3160 } else {
3161 builder->WriteUInt32(name_value_block.size());
3164 // Serialize each header.
3165 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
3166 it != name_value_block.end();
3167 ++it) {
3168 if (protocol_version() <= SPDY2) {
3169 builder->WriteStringPiece16(it->first);
3170 builder->WriteStringPiece16(it->second);
3171 } else {
3172 builder->WriteStringPiece32(it->first);
3173 builder->WriteStringPiece32(it->second);
3178 void SpdyFramer::SerializeNameValueBlock(
3179 SpdyFrameBuilder* builder,
3180 const SpdyFrameWithNameValueBlockIR& frame) {
3181 CHECK_GE(SPDY3, protocol_version());
3182 if (!enable_compression_) {
3183 return SerializeNameValueBlockWithoutCompression(builder,
3184 frame.name_value_block());
3187 // First build an uncompressed version to be fed into the compressor.
3188 const size_t uncompressed_len = GetSerializedLength(
3189 protocol_version(), &(frame.name_value_block()));
3190 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3191 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
3192 frame.name_value_block());
3193 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
3195 z_stream* compressor = GetHeaderCompressor();
3196 if (!compressor) {
3197 LOG(DFATAL) << "Could not obtain compressor.";
3198 return;
3200 // Create an output frame.
3201 // Since we'll be performing lots of flushes when compressing the data,
3202 // zlib's lower bounds may be insufficient.
3204 // TODO(akalin): Avoid the duplicate calculation with
3205 // GetSerializedLength(const SpdyHeaderBlock&).
3206 const int compressed_max_size =
3207 2 * deflateBound(compressor, uncompressed_len);
3209 // TODO(phajdan.jr): Clean up after we no longer need
3210 // to workaround http://crbug.com/139744.
3211 #if defined(USE_SYSTEM_ZLIB)
3212 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
3213 compressor->avail_in = uncompressed_len;
3214 #endif // defined(USE_SYSTEM_ZLIB)
3215 compressor->next_out = reinterpret_cast<Bytef*>(
3216 builder->GetWritableBuffer(compressed_max_size));
3217 compressor->avail_out = compressed_max_size;
3219 // TODO(phajdan.jr): Clean up after we no longer need
3220 // to workaround http://crbug.com/139744.
3221 #if defined(USE_SYSTEM_ZLIB)
3222 int rv = deflate(compressor, Z_SYNC_FLUSH);
3223 if (rv != Z_OK) { // How can we know that it compressed everything?
3224 // This shouldn't happen, right?
3225 LOG(WARNING) << "deflate failure: " << rv;
3226 // TODO(akalin): Upstream this return.
3227 return;
3229 #else
3230 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
3231 #endif // defined(USE_SYSTEM_ZLIB)
3233 int compressed_size = compressed_max_size - compressor->avail_out;
3234 builder->Seek(compressed_size);
3235 builder->RewriteLength(*this);
3238 } // namespace net