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 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't
6 // constantly adding and subtracting header sizes; this is ugly and error-
9 #include "net/spdy/spdy_framer.h"
11 #include "base/lazy_instance.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/metrics/stats_counters.h"
14 #include "base/third_party/valgrind/memcheck.h"
15 #include "net/spdy/spdy_frame_builder.h"
16 #include "net/spdy/spdy_frame_reader.h"
17 #include "net/spdy/spdy_bitmasks.h"
18 #include "third_party/zlib/zlib.h"
26 // Compute the id of our dictionary so that we know we're using the
27 // right one when asked for it.
28 uLong CalculateDictionaryId(const char* dictionary,
29 const size_t dictionary_size) {
30 uLong initial_value = adler32(0L, Z_NULL, 0);
31 return adler32(initial_value,
32 reinterpret_cast<const Bytef*>(dictionary),
36 struct DictionaryIds {
38 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
39 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
41 const uLong v2_dictionary_id;
42 const uLong v3_dictionary_id;
45 // Adler ID for the SPDY header compressor dictionaries. Note that they are
46 // initialized lazily to avoid static initializers.
47 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
49 // Used to indicate no flags in a SPDY flags field.
50 const uint8 kNoFlags = 0;
54 const SpdyStreamId SpdyFramer::kInvalidStream = -1;
55 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
56 // The size of the control frame buffer. Must be >= the minimum size of the
57 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
58 // calculation details.
59 const size_t SpdyFramer::kControlFrameBufferSize = 18;
61 #ifdef DEBUG_SPDY_STATE_CHANGES
62 #define CHANGE_STATE(newstate) \
64 DVLOG(1) << "Changing state from: " \
65 << StateToString(state_) \
66 << " to " << StateToString(newstate) << "\n"; \
67 DCHECK(state_ != SPDY_ERROR); \
68 DCHECK_EQ(previous_state_, state_); \
69 previous_state_ = state_; \
73 #define CHANGE_STATE(newstate) \
75 DCHECK(state_ != SPDY_ERROR); \
76 DCHECK_EQ(previous_state_, state_); \
77 previous_state_ = state_; \
82 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version,
85 ConvertFlagsAndIdForSpdy2(&wire);
87 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
90 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
91 : flags_(flags), id_(id & 0x00ffffff) {
92 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large.";
95 uint32 SettingsFlagsAndId::GetWireFormat(int version) const {
96 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
98 ConvertFlagsAndIdForSpdy2(&wire);
103 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
104 // This method is used to preserve buggy behavior and works on both
105 // little-endian and big-endian hosts.
106 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
107 // as well as vice versa).
108 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
109 uint8* wire_array = reinterpret_cast<uint8*>(val);
110 std::swap(wire_array[0], wire_array[3]);
111 std::swap(wire_array[1], wire_array[2]);
114 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
119 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
120 const char* rst_stream_data,
125 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
126 : current_frame_buffer_(new char[kControlFrameBufferSize]),
127 enable_compression_(true),
129 debug_visitor_(NULL),
130 display_protocol_("SPDY"),
131 spdy_version_(version),
132 syn_frame_processed_(false),
133 probable_http_response_(false) {
134 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
135 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
139 SpdyFramer::~SpdyFramer() {
140 if (header_compressor_.get()) {
141 deflateEnd(header_compressor_.get());
143 if (header_decompressor_.get()) {
144 inflateEnd(header_decompressor_.get());
148 void SpdyFramer::Reset() {
150 previous_state_ = SPDY_RESET;
151 error_code_ = SPDY_NO_ERROR;
152 remaining_data_length_ = 0;
153 remaining_control_header_ = 0;
154 current_frame_buffer_length_ = 0;
155 current_frame_type_ = DATA;
156 current_frame_flags_ = 0;
157 current_frame_length_ = 0;
158 current_frame_stream_id_ = kInvalidStream;
159 settings_scratch_.Reset();
162 size_t SpdyFramer::GetDataFrameMinimumSize() const {
163 // Size, in bytes, of the data frame header. Future versions of SPDY
164 // will likely vary this, so we allow for the flexibility of a function call
165 // for this value as opposed to a constant.
169 // Size, in bytes, of the control frame header.
170 size_t SpdyFramer::GetControlFrameHeaderSize() const {
171 switch (protocol_version()) {
177 LOG(DFATAL) << "Unhandled SPDY version.";
181 size_t SpdyFramer::GetSynStreamMinimumSize() const {
182 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
184 if (spdy_version_ < 4) {
186 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
187 // + 1 (unused, was credential slot)
188 return GetControlFrameHeaderSize() + 10;
191 // frame prefix + 4 (priority)
192 return GetControlFrameHeaderSize() + 4;
196 size_t SpdyFramer::GetSynReplyMinimumSize() const {
197 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
199 size_t size = GetControlFrameHeaderSize();
200 if (spdy_version_ < 4) {
202 // control frame header + 4 (stream IDs)
206 // In SPDY 2, there were 2 unused bytes before payload.
207 if (protocol_version() < 3) {
214 size_t SpdyFramer::GetRstStreamMinimumSize() const {
215 // Size, in bytes, of a RST_STREAM frame.
216 if (spdy_version_ < 4) {
218 // control frame header + 4 (stream id) + 4 (status code)
219 return GetControlFrameHeaderSize() + 8;
222 // frame prefix + 4 (status code)
223 return GetControlFrameHeaderSize() + 4;
227 size_t SpdyFramer::GetSettingsMinimumSize() const {
228 // Size, in bytes, of a SETTINGS frame not including the IDs and values
229 // from the variable-length value block. Calculated as:
230 // control frame header + 4 (number of ID/value pairs)
231 return GetControlFrameHeaderSize() + 4;
234 size_t SpdyFramer::GetPingSize() const {
235 // Size, in bytes, of this PING frame.
236 if (spdy_version_ < 4) {
238 // control frame header + 4 (id)
239 return GetControlFrameHeaderSize() + 4;
242 // control frame header + 8 (id)
243 return GetControlFrameHeaderSize() + 8;
247 size_t SpdyFramer::GetGoAwayMinimumSize() const {
248 // Size, in bytes, of this GOAWAY frame. Calculated as:
249 // 1. Control frame header size
250 size_t size = GetControlFrameHeaderSize();
252 // 2. Last good stream id (4 bytes)
255 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
256 if (protocol_version() >= 3) {
263 size_t SpdyFramer::GetHeadersMinimumSize() const {
264 // Size, in bytes, of a HEADERS frame not including the variable-length
266 size_t size = GetControlFrameHeaderSize();
267 if (spdy_version_ < 4) {
269 // control frame header + 4 (stream IDs)
273 // In SPDY 2, there were 2 unused bytes before payload.
274 if (protocol_version() < 3) {
281 size_t SpdyFramer::GetWindowUpdateSize() const {
282 // Size, in bytes, of a WINDOW_UPDATE frame.
283 if (spdy_version_ < 4) {
285 // control frame header + 4 (stream id) + 4 (delta)
286 return GetControlFrameHeaderSize() + 8;
289 // frame prefix + 4 (delta)
290 return GetControlFrameHeaderSize() + 4;
294 size_t SpdyFramer::GetBlockedSize() const {
295 DCHECK_LE(4, protocol_version());
296 // Size, in bytes, of a BLOCKED frame.
297 // The BLOCKED frame has no payload beyond the control frame header.
298 return GetControlFrameHeaderSize();
301 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
302 DCHECK_LE(4, protocol_version());
303 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
304 // Calculated as frame prefix + 4 (promised stream id).
305 return GetControlFrameHeaderSize() + 4;
308 size_t SpdyFramer::GetFrameMinimumSize() const {
309 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
312 size_t SpdyFramer::GetFrameMaximumSize() const {
313 return (protocol_version() < 4) ? 0xffffff : 0xffff;
316 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
317 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
320 const char* SpdyFramer::StateToString(int state) {
324 case SPDY_AUTO_RESET:
328 case SPDY_READING_COMMON_HEADER:
329 return "READING_COMMON_HEADER";
330 case SPDY_CONTROL_FRAME_PAYLOAD:
331 return "CONTROL_FRAME_PAYLOAD";
332 case SPDY_IGNORE_REMAINING_PAYLOAD:
333 return "IGNORE_REMAINING_PAYLOAD";
334 case SPDY_FORWARD_STREAM_FRAME:
335 return "FORWARD_STREAM_FRAME";
336 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
337 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
338 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
339 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
340 case SPDY_GOAWAY_FRAME_PAYLOAD:
341 return "SPDY_GOAWAY_FRAME_PAYLOAD";
342 case SPDY_RST_STREAM_FRAME_PAYLOAD:
343 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
344 case SPDY_SETTINGS_FRAME_PAYLOAD:
345 return "SPDY_SETTINGS_FRAME_PAYLOAD";
347 return "UNKNOWN_STATE";
350 void SpdyFramer::set_error(SpdyError error) {
353 CHANGE_STATE(SPDY_ERROR);
354 visitor_->OnError(this);
357 const char* SpdyFramer::ErrorCodeToString(int error_code) {
358 switch (error_code) {
361 case SPDY_INVALID_CONTROL_FRAME:
362 return "INVALID_CONTROL_FRAME";
363 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
364 return "CONTROL_PAYLOAD_TOO_LARGE";
365 case SPDY_ZLIB_INIT_FAILURE:
366 return "ZLIB_INIT_FAILURE";
367 case SPDY_UNSUPPORTED_VERSION:
368 return "UNSUPPORTED_VERSION";
369 case SPDY_DECOMPRESS_FAILURE:
370 return "DECOMPRESS_FAILURE";
371 case SPDY_COMPRESS_FAILURE:
372 return "COMPRESS_FAILURE";
373 case SPDY_INVALID_DATA_FRAME_FLAGS:
374 return "SPDY_INVALID_DATA_FRAME_FLAGS";
375 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
376 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
378 return "UNKNOWN_ERROR";
381 const char* SpdyFramer::StatusCodeToString(int status_code) {
382 switch (status_code) {
383 case RST_STREAM_INVALID:
385 case RST_STREAM_PROTOCOL_ERROR:
386 return "PROTOCOL_ERROR";
387 case RST_STREAM_INVALID_STREAM:
388 return "INVALID_STREAM";
389 case RST_STREAM_REFUSED_STREAM:
390 return "REFUSED_STREAM";
391 case RST_STREAM_UNSUPPORTED_VERSION:
392 return "UNSUPPORTED_VERSION";
393 case RST_STREAM_CANCEL:
395 case RST_STREAM_INTERNAL_ERROR:
396 return "INTERNAL_ERROR";
397 case RST_STREAM_FLOW_CONTROL_ERROR:
398 return "FLOW_CONTROL_ERROR";
399 case RST_STREAM_STREAM_IN_USE:
400 return "STREAM_IN_USE";
401 case RST_STREAM_STREAM_ALREADY_CLOSED:
402 return "STREAM_ALREADY_CLOSED";
403 case RST_STREAM_INVALID_CREDENTIALS:
404 return "INVALID_CREDENTIALS";
405 case RST_STREAM_FRAME_TOO_LARGE:
406 return "FRAME_TOO_LARGE";
408 return "UNKNOWN_STATUS";
411 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
432 return "WINDOW_UPDATE";
438 return "PUSH_PROMISE";
440 return "UNKNOWN_CONTROL_TYPE";
443 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
447 size_t original_len = len;
449 previous_state_ = state_;
454 case SPDY_AUTO_RESET:
458 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
462 case SPDY_READING_COMMON_HEADER: {
463 size_t bytes_read = ProcessCommonHeader(data, len);
469 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
470 // Control frames that contain header blocks
471 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE)
472 // take a different path through the state machine - they
474 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
475 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
477 // SETTINGS frames take a slightly modified route:
478 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
479 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
481 // All other control frames will use the alternate route directly to
482 // SPDY_CONTROL_FRAME_PAYLOAD
483 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
489 case SPDY_SETTINGS_FRAME_PAYLOAD: {
490 int bytes_read = ProcessSettingsFramePayload(data, len);
496 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
497 int bytes_read = ProcessControlFrameHeaderBlock(data, len);
503 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
504 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
510 case SPDY_GOAWAY_FRAME_PAYLOAD: {
511 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
517 case SPDY_CONTROL_FRAME_PAYLOAD: {
518 size_t bytes_read = ProcessControlFramePayload(data, len);
524 case SPDY_IGNORE_REMAINING_PAYLOAD:
525 // control frame has too-large payload
526 // intentional fallthrough
527 case SPDY_FORWARD_STREAM_FRAME: {
528 size_t bytes_read = ProcessDataFramePayload(data, len);
534 LOG(DFATAL) << "Invalid value for " << display_protocol_
535 << " framer state: " << state_;
536 // This ensures that we don't infinite-loop if state_ gets an
537 // invalid value somehow, such as due to a SpdyFramer getting deleted
538 // from a callback it calls.
541 } while (state_ != previous_state_);
543 DCHECK(len == 0 || state_ == SPDY_ERROR);
544 if (current_frame_buffer_length_ == 0 &&
545 remaining_data_length_ == 0 &&
546 remaining_control_header_ == 0) {
547 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
548 << "State: " << StateToString(state_);
551 return original_len - len;
554 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
555 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
557 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
559 size_t original_len = len;
561 // Update current frame buffer as needed.
562 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
563 size_t bytes_desired =
564 GetControlFrameHeaderSize() - current_frame_buffer_length_;
565 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
568 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
569 // Not enough information to do anything meaningful.
570 return original_len - len;
573 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
574 // when processing DATA frames below.
575 scoped_ptr<SpdyFrameReader> reader(
576 new SpdyFrameReader(current_frame_buffer_.get(),
577 current_frame_buffer_length_));
580 bool is_control_frame = false;
582 uint16 control_frame_type_field = DATA;
583 // ProcessControlFrameHeader() will set current_frame_type_ to the
584 // correct value if this is a valid control frame.
585 current_frame_type_ = DATA;
586 if (protocol_version() < 4) {
587 bool successful_read = reader->ReadUInt16(&version);
588 DCHECK(successful_read);
589 is_control_frame = (version & kControlFlagMask) != 0;
590 version &= ~kControlFlagMask; // Only valid for control frames.
592 if (is_control_frame) {
593 // We check control_frame_type_field's validity in
594 // ProcessControlFrameHeader().
595 successful_read = reader->ReadUInt16(&control_frame_type_field);
598 successful_read = reader->ReadUInt31(¤t_frame_stream_id_);
600 DCHECK(successful_read);
602 successful_read = reader->ReadUInt8(¤t_frame_flags_);
603 DCHECK(successful_read);
605 uint32 length_field = 0;
606 successful_read = reader->ReadUInt24(&length_field);
607 DCHECK(successful_read);
608 remaining_data_length_ = length_field;
609 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
611 version = protocol_version();
612 uint16 length_field = 0;
613 bool successful_read = reader->ReadUInt16(&length_field);
614 DCHECK(successful_read);
615 current_frame_length_ = length_field;
617 uint8 control_frame_type_field_uint8 = DATA;
618 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
619 DCHECK(successful_read);
620 // We check control_frame_type_field's validity in
621 // ProcessControlFrameHeader().
622 control_frame_type_field = control_frame_type_field_uint8;
623 is_control_frame = (control_frame_type_field != DATA);
625 successful_read = reader->ReadUInt8(¤t_frame_flags_);
626 DCHECK(successful_read);
628 successful_read = reader->ReadUInt31(¤t_frame_stream_id_);
629 DCHECK(successful_read);
631 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
633 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
634 : GetDataFrameMinimumSize(),
635 reader->GetBytesConsumed());
636 DCHECK_EQ(current_frame_length_,
637 remaining_data_length_ + reader->GetBytesConsumed());
639 // This is just a sanity check for help debugging early frame errors.
640 if (remaining_data_length_ > 1000000u) {
641 // The strncmp for 5 is safe because we only hit this point if we
642 // have kMinCommonHeader (8) bytes
643 if (!syn_frame_processed_ &&
644 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
645 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
647 probable_http_response_ = true;
649 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
650 << " session is likely corrupt.";
654 // if we're here, then we have the common header all received.
655 if (!is_control_frame) {
656 if (current_frame_flags_ & ~DATA_FLAG_FIN) {
657 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
659 visitor_->OnDataFrameHeader(current_frame_stream_id_,
660 remaining_data_length_,
661 current_frame_flags_ & DATA_FLAG_FIN);
662 if (remaining_data_length_ > 0) {
663 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
666 if (current_frame_flags_ & DATA_FLAG_FIN) {
667 visitor_->OnStreamFrameData(
668 current_frame_stream_id_, NULL, 0, true);
670 CHANGE_STATE(SPDY_AUTO_RESET);
673 } else if (version != spdy_version_) {
674 // We check version before we check validity: version can never be
675 // 'invalid', it can only be unsupported.
676 DVLOG(1) << "Unsupported SPDY version " << version
677 << " (expected " << spdy_version_ << ")";
678 set_error(SPDY_UNSUPPORTED_VERSION);
680 ProcessControlFrameHeader(control_frame_type_field);
683 return original_len - len;
686 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
687 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
688 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
690 if (control_frame_type_field < FIRST_CONTROL_TYPE ||
691 control_frame_type_field > LAST_CONTROL_TYPE) {
692 set_error(SPDY_INVALID_CONTROL_FRAME);
696 current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
698 if (current_frame_type_ == NOOP) {
699 DVLOG(1) << "NOOP control frame found. Ignoring.";
700 CHANGE_STATE(SPDY_AUTO_RESET);
704 if (current_frame_type_ == CREDENTIAL) {
705 DCHECK_EQ(3, protocol_version());
706 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
707 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
711 // Do some sanity checking on the control frame sizes and flags.
712 switch (current_frame_type_) {
714 DCHECK_GT(4, spdy_version_);
715 if (current_frame_length_ < GetSynStreamMinimumSize()) {
716 set_error(SPDY_INVALID_CONTROL_FRAME);
717 } else if (current_frame_flags_ &
718 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
719 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
723 if (current_frame_length_ < GetSynReplyMinimumSize()) {
724 set_error(SPDY_INVALID_CONTROL_FRAME);
725 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
726 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
730 // For SPDY versions < 4, the header has a fixed length.
731 // For SPDY version 4 and up, the RST_STREAM frame may include optional
732 // opaque data, so we only have a lower limit on the frame size.
733 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
734 protocol_version() < 4) ||
735 (current_frame_length_ < GetRstStreamMinimumSize() &&
736 protocol_version() >= 4)) {
737 set_error(SPDY_INVALID_CONTROL_FRAME);
738 } else if (current_frame_flags_ != 0) {
739 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
743 // Make sure that we have an integral number of 8-byte key/value pairs,
744 // plus a 4-byte length field.
745 if (current_frame_length_ < GetSettingsMinimumSize() ||
746 (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) {
747 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
748 << current_frame_length_;
749 set_error(SPDY_INVALID_CONTROL_FRAME);
750 } else if (current_frame_flags_ &
751 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
752 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
756 if (current_frame_length_ != GetPingSize()) {
757 set_error(SPDY_INVALID_CONTROL_FRAME);
758 } else if (current_frame_flags_ != 0) {
759 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
764 // For SPDY version < 4, there are only mandatory fields and the header
765 // has a fixed length. For SPDY version >= 4, optional opaque data may
766 // be appended to the GOAWAY frame, thus there is only a minimal length
768 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
769 protocol_version() < 4) ||
770 (current_frame_length_ < GetGoAwayMinimumSize() &&
771 protocol_version() >= 4)) {
772 set_error(SPDY_INVALID_CONTROL_FRAME);
773 } else if (current_frame_flags_ != 0) {
774 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
780 size_t min_size = GetHeadersMinimumSize();
781 if (spdy_version_ > 3 &&
782 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
785 if (current_frame_length_ < min_size) {
786 set_error(SPDY_INVALID_CONTROL_FRAME);
787 } else if (spdy_version_ < 4 &&
788 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
789 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
790 } else if (spdy_version_ > 3 && current_frame_flags_ &
791 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY)) {
792 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
797 if (current_frame_length_ != GetWindowUpdateSize()) {
798 set_error(SPDY_INVALID_CONTROL_FRAME);
799 } else if (current_frame_flags_ != 0) {
800 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
804 if (current_frame_length_ != GetBlockedSize()) {
805 set_error(SPDY_INVALID_CONTROL_FRAME);
806 } else if (current_frame_flags_ != 0) {
807 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
811 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
812 set_error(SPDY_INVALID_CONTROL_FRAME);
813 } else if (current_frame_flags_ != 0) {
814 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
818 LOG(WARNING) << "Valid " << display_protocol_
819 << " control frame with unhandled type: "
820 << current_frame_type_;
821 // This branch should be unreachable because of the frame type bounds
822 // check above. However, we DLOG(FATAL) here in an effort to painfully
823 // club the head of the developer who failed to keep this file in sync
824 // with spdy_protocol.h.
826 set_error(SPDY_INVALID_CONTROL_FRAME);
830 if (state_ == SPDY_ERROR) {
834 if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
835 DLOG(WARNING) << "Received control frame with way too big of a payload: "
836 << current_frame_length_;
837 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
841 if (current_frame_type_ == GOAWAY) {
842 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
846 if (current_frame_type_ == RST_STREAM) {
847 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
851 // Determine the frame size without variable-length data.
852 int32 frame_size_without_variable_data;
853 switch (current_frame_type_) {
855 syn_frame_processed_ = true;
856 frame_size_without_variable_data = GetSynStreamMinimumSize();
859 syn_frame_processed_ = true;
860 frame_size_without_variable_data = GetSynReplyMinimumSize();
863 frame_size_without_variable_data = GetSettingsMinimumSize();
866 frame_size_without_variable_data = GetHeadersMinimumSize();
867 if (spdy_version_ > 3 && current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
868 frame_size_without_variable_data += 4; // priority
872 frame_size_without_variable_data = GetPushPromiseMinimumSize();
875 frame_size_without_variable_data = -1;
879 if ((frame_size_without_variable_data == -1) &&
880 (current_frame_length_ > kControlFrameBufferSize)) {
881 // We should already be in an error state. Double-check.
882 DCHECK_EQ(SPDY_ERROR, state_);
883 if (state_ != SPDY_ERROR) {
884 LOG(DFATAL) << display_protocol_
885 << " control frame buffer too small for fixed-length frame.";
886 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
891 if (frame_size_without_variable_data > 0) {
892 // We have a control frame with a header block. We need to parse the
893 // remainder of the control frame's header before we can parse the header
894 // block. The start of the header block varies with the control type.
895 DCHECK_GE(frame_size_without_variable_data,
896 static_cast<int32>(current_frame_buffer_length_));
897 remaining_control_header_ = frame_size_without_variable_data -
898 current_frame_buffer_length_;
900 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
904 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
907 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
909 size_t bytes_to_read = std::min(*len, max_bytes);
910 if (bytes_to_read > 0) {
911 DCHECK_GE(kControlFrameBufferSize,
912 current_frame_buffer_length_ + bytes_to_read);
913 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
916 current_frame_buffer_length_ += bytes_to_read;
917 *data += bytes_to_read;
918 *len -= bytes_to_read;
920 return bytes_to_read;
923 size_t SpdyFramer::GetSerializedLength(const int spdy_version,
924 const SpdyHeaderBlock* headers) {
925 const size_t num_name_value_pairs_size
926 = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32);
927 const size_t length_of_name_size = num_name_value_pairs_size;
928 const size_t length_of_value_size = num_name_value_pairs_size;
930 size_t total_length = num_name_value_pairs_size;
931 for (SpdyHeaderBlock::const_iterator it = headers->begin();
932 it != headers->end();
934 // We add space for the length of the name and the length of the value as
935 // well as the length of the name and the length of the value.
936 total_length += length_of_name_size + it->first.size() +
937 length_of_value_size + it->second.size();
942 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
943 const int spdy_version,
944 const SpdyHeaderBlock* headers) {
945 if (spdy_version < 3) {
946 frame->WriteUInt16(headers->size()); // Number of headers.
948 frame->WriteUInt32(headers->size()); // Number of headers.
950 SpdyHeaderBlock::const_iterator it;
951 for (it = headers->begin(); it != headers->end(); ++it) {
952 if (spdy_version < 3) {
953 frame->WriteString(it->first);
954 frame->WriteString(it->second);
956 frame->WriteStringPiece32(it->first);
957 frame->WriteStringPiece32(it->second);
962 // TODO(phajdan.jr): Clean up after we no longer need
963 // to workaround http://crbug.com/139744.
964 #if !defined(USE_SYSTEM_ZLIB)
966 // These constants are used by zlib to differentiate between normal data and
967 // cookie data. Cookie data is handled specially by zlib when compressing.
969 // kZStandardData is compressed normally, save that it will never match
970 // against any other class of data in the window.
971 kZStandardData = Z_CLASS_STANDARD,
972 // kZCookieData is compressed in its own Huffman blocks and only matches in
973 // its entirety and only against other kZCookieData blocks. Any matches must
974 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
975 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
977 kZCookieData = Z_CLASS_COOKIE,
978 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
979 // against the window.
980 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
983 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
984 // needed when switching between classes of data.
985 static void WriteZ(const base::StringPiece& data,
990 // If we are switching from standard to non-standard data then we need to end
991 // the current Huffman context to avoid it leaking between them.
992 if (out->clas == kZStandardData &&
993 clas != kZStandardData) {
995 rv = deflate(out, Z_PARTIAL_FLUSH);
997 DCHECK_EQ(0u, out->avail_in);
998 DCHECK_LT(0u, out->avail_out);
1001 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1002 out->avail_in = data.size();
1004 if (clas == kZStandardData) {
1005 rv = deflate(out, Z_NO_FLUSH);
1007 rv = deflate(out, Z_PARTIAL_FLUSH);
1009 if (!data.empty()) {
1010 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1011 DCHECK_EQ(Z_OK, rv);
1013 DCHECK_EQ(0u, out->avail_in);
1014 DCHECK_LT(0u, out->avail_out);
1017 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
1018 static void WriteLengthZ(size_t n,
1023 DCHECK_LE(length, sizeof(buf));
1024 for (unsigned i = 1; i <= length; i++) {
1025 buf[length - i] = n;
1028 WriteZ(base::StringPiece(buf, length), clas, out);
1031 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1032 // manner that resists the length of the compressed data from compromising
1034 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1035 z_stream* z) const {
1036 unsigned length_length = 4;
1037 if (spdy_version_ < 3)
1040 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1042 std::map<std::string, std::string>::const_iterator it;
1043 for (it = headers->begin(); it != headers->end(); ++it) {
1044 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1045 WriteZ(it->first, kZStandardData, z);
1047 if (it->first == "cookie") {
1048 // We require the cookie values (save for the last) to end with a
1049 // semicolon and (save for the first) to start with a space. This is
1050 // typically the format that we are given them in but we reserialize them
1053 std::vector<base::StringPiece> cookie_values;
1054 size_t cookie_length = 0;
1055 base::StringPiece cookie_data(it->second);
1058 while (!cookie_data.empty() &&
1059 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1060 cookie_data.remove_prefix(1);
1062 if (cookie_data.empty())
1066 for (i = 0; i < cookie_data.size(); i++) {
1067 if (cookie_data[i] == ';')
1070 if (i < cookie_data.size()) {
1071 cookie_values.push_back(cookie_data.substr(0, i));
1072 cookie_length += i + 2 /* semicolon and space */;
1073 cookie_data.remove_prefix(i + 1);
1075 cookie_values.push_back(cookie_data);
1076 cookie_length += cookie_data.size();
1077 cookie_data.remove_prefix(i);
1081 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1082 for (size_t i = 0; i < cookie_values.size(); i++) {
1084 // Since zlib will only back-reference complete cookies, a cookie that
1085 // is currently last (and so doesn't have a trailing semicolon) won't
1086 // match if it's later in a non-final position. The same is true of
1087 // the first cookie.
1088 if (i == 0 && cookie_values.size() == 1) {
1089 cookie = cookie_values[i].as_string();
1090 } else if (i == 0) {
1091 cookie = cookie_values[i].as_string() + ";";
1092 } else if (i < cookie_values.size() - 1) {
1093 cookie = " " + cookie_values[i].as_string() + ";";
1095 cookie = " " + cookie_values[i].as_string();
1097 WriteZ(cookie, kZCookieData, z);
1099 } else if (it->first == "accept" ||
1100 it->first == "accept-charset" ||
1101 it->first == "accept-encoding" ||
1102 it->first == "accept-language" ||
1103 it->first == "host" ||
1104 it->first == "version" ||
1105 it->first == "method" ||
1106 it->first == "scheme" ||
1107 it->first == ":host" ||
1108 it->first == ":version" ||
1109 it->first == ":method" ||
1110 it->first == ":scheme" ||
1111 it->first == "user-agent") {
1112 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1113 WriteZ(it->second, kZStandardData, z);
1115 // Non-whitelisted headers are Huffman compressed in their own block, but
1116 // don't match against the window.
1117 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1118 WriteZ(it->second, kZHuffmanOnlyData, z);
1123 int rv = deflate(z, Z_SYNC_FLUSH);
1124 DCHECK_EQ(Z_OK, rv);
1125 z->clas = kZStandardData;
1127 #endif // !defined(USE_SYSTEM_ZLIB)
1129 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1131 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1132 const size_t original_len = len;
1134 if (remaining_control_header_ > 0) {
1135 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1136 remaining_control_header_);
1137 remaining_control_header_ -= bytes_read;
1138 remaining_data_length_ -= bytes_read;
1141 if (remaining_control_header_ == 0) {
1142 SpdyFrameReader reader(current_frame_buffer_.get(),
1143 current_frame_buffer_length_);
1144 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1146 switch (current_frame_type_) {
1149 DCHECK_GT(4, spdy_version_);
1150 bool successful_read = true;
1151 if (spdy_version_ < 4) {
1152 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1153 DCHECK(successful_read);
1155 if (current_frame_stream_id_ == 0) {
1156 set_error(SPDY_INVALID_CONTROL_FRAME);
1160 SpdyStreamId associated_to_stream_id = kInvalidStream;
1161 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1162 DCHECK(successful_read);
1164 SpdyPriority priority = 0;
1165 successful_read = reader.ReadUInt8(&priority);
1166 DCHECK(successful_read);
1167 if (protocol_version() < 3) {
1168 priority = priority >> 6;
1170 priority = priority >> 5;
1173 // Seek past unused byte; used to be credential slot in SPDY 3.
1176 DCHECK(reader.IsDoneReading());
1177 if (debug_visitor_) {
1178 debug_visitor_->OnReceiveCompressedFrame(
1179 current_frame_stream_id_,
1180 current_frame_type_,
1181 current_frame_length_);
1183 visitor_->OnSynStream(
1184 current_frame_stream_id_,
1185 associated_to_stream_id,
1187 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1188 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1190 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1193 visitor_->OnSettings(current_frame_flags_ &
1194 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1195 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1199 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1201 if (spdy_version_ > 3) {
1202 DCHECK_EQ(HEADERS, current_frame_type_);
1204 bool successful_read = true;
1205 if (spdy_version_ < 4) {
1206 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1207 DCHECK(successful_read);
1209 if (current_frame_stream_id_ == 0) {
1210 set_error(SPDY_INVALID_CONTROL_FRAME);
1213 if (protocol_version() < 3) {
1214 // SPDY 2 had two unused bytes here. Seek past them.
1217 const bool has_priority =
1218 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1219 uint32 priority = 0;
1220 if (protocol_version() > 3 && has_priority) {
1221 successful_read = reader.ReadUInt31(&priority);
1222 DCHECK(successful_read);
1224 DCHECK(reader.IsDoneReading());
1225 if (debug_visitor_) {
1226 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1227 SpdyFrameType reported_type = current_frame_type_;
1228 if (protocol_version() > 3 && has_priority) {
1229 reported_type = SYN_STREAM;
1231 debug_visitor_->OnReceiveCompressedFrame(
1232 current_frame_stream_id_,
1234 current_frame_length_);
1236 if (current_frame_type_ == SYN_REPLY) {
1237 visitor_->OnSynReply(
1238 current_frame_stream_id_,
1239 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1240 } else if (spdy_version_ > 3 &&
1241 current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1242 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1243 // can be made independent of wire changes.
1244 visitor_->OnSynStream(
1245 current_frame_stream_id_,
1246 0, // associated_to_stream_id
1248 current_frame_flags_ & CONTROL_FLAG_FIN,
1249 false); // unidirectional
1251 visitor_->OnHeaders(
1252 current_frame_stream_id_,
1253 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1256 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1260 DCHECK_LE(4, protocol_version());
1261 if (current_frame_stream_id_ == 0) {
1262 set_error(SPDY_INVALID_CONTROL_FRAME);
1265 SpdyStreamId promised_stream_id = kInvalidStream;
1266 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1267 DCHECK(successful_read);
1268 DCHECK(reader.IsDoneReading());
1269 if (promised_stream_id == 0) {
1270 set_error(SPDY_INVALID_CONTROL_FRAME);
1273 if (debug_visitor_) {
1274 debug_visitor_->OnReceiveCompressedFrame(
1275 current_frame_stream_id_,
1276 current_frame_type_,
1277 current_frame_length_);
1279 visitor_->OnPushPromise(current_frame_stream_id_, promised_stream_id);
1281 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1287 return original_len - len;
1290 // Does not buffer the control payload. Instead, either passes directly to the
1291 // visitor or decompresses and then passes directly to the visitor, via
1292 // IncrementallyDeliverControlFrameHeaderData() or
1293 // IncrementallyDecompressControlFrameHeaderData() respectively.
1294 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1296 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1298 bool processed_successfully = true;
1299 if (current_frame_type_ != SYN_STREAM &&
1300 current_frame_type_ != SYN_REPLY &&
1301 current_frame_type_ != HEADERS &&
1302 current_frame_type_ != PUSH_PROMISE) {
1303 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1305 size_t process_bytes = std::min(data_len, remaining_data_length_);
1306 if (process_bytes > 0) {
1307 if (enable_compression_) {
1308 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1309 current_frame_stream_id_, data, process_bytes);
1311 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1312 current_frame_stream_id_, data, process_bytes);
1315 remaining_data_length_ -= process_bytes;
1318 // Handle the case that there is no futher data in this frame.
1319 if (remaining_data_length_ == 0 && processed_successfully) {
1320 // The complete header block has been delivered. We send a zero-length
1321 // OnControlFrameHeaderData() to indicate this.
1322 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1324 // If this is a FIN, tell the caller.
1325 if (current_frame_flags_ & CONTROL_FLAG_FIN) {
1326 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1329 CHANGE_STATE(SPDY_AUTO_RESET);
1333 if (!processed_successfully) {
1337 // Return amount processed.
1338 return process_bytes;
1341 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1343 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1344 DCHECK_EQ(SETTINGS, current_frame_type_);
1345 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1346 size_t processed_bytes = 0;
1348 // Loop over our incoming data.
1349 while (unprocessed_bytes > 0) {
1350 // Process up to one setting at a time.
1351 size_t processing = std::min(
1353 static_cast<size_t>(8 - settings_scratch_.setting_buf_len));
1355 // Check if we have a complete setting in our input.
1356 if (processing == 8) {
1357 // Parse the setting directly out of the input without buffering.
1358 if (!ProcessSetting(data + processed_bytes)) {
1359 set_error(SPDY_INVALID_CONTROL_FRAME);
1360 return processed_bytes;
1363 // Continue updating settings_scratch_.setting_buf.
1364 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1365 data + processed_bytes,
1367 settings_scratch_.setting_buf_len += processing;
1369 // Check if we have a complete setting buffered.
1370 if (settings_scratch_.setting_buf_len == 8) {
1371 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1372 set_error(SPDY_INVALID_CONTROL_FRAME);
1373 return processed_bytes;
1375 // Reset settings_scratch_.setting_buf for our next setting.
1376 settings_scratch_.setting_buf_len = 0;
1381 unprocessed_bytes -= processing;
1382 processed_bytes += processing;
1385 // Check if we're done handling this SETTINGS frame.
1386 remaining_data_length_ -= processed_bytes;
1387 if (remaining_data_length_ == 0) {
1388 CHANGE_STATE(SPDY_AUTO_RESET);
1391 return processed_bytes;
1394 bool SpdyFramer::ProcessSetting(const char* data) {
1396 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1397 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1398 SettingsFlagsAndId id_and_flags =
1399 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
1400 uint8 flags = id_and_flags.flags();
1401 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1404 switch (id_and_flags.id()) {
1405 case SETTINGS_UPLOAD_BANDWIDTH:
1406 case SETTINGS_DOWNLOAD_BANDWIDTH:
1407 case SETTINGS_ROUND_TRIP_TIME:
1408 case SETTINGS_MAX_CONCURRENT_STREAMS:
1409 case SETTINGS_CURRENT_CWND:
1410 case SETTINGS_DOWNLOAD_RETRANS_RATE:
1411 case SETTINGS_INITIAL_WINDOW_SIZE:
1415 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
1418 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());
1420 // Detect duplciates.
1421 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
1422 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1423 << " in " << display_protocol_ << " SETTINGS frame "
1424 << "(last settikng id was "
1425 << settings_scratch_.last_setting_id << ").";
1428 settings_scratch_.last_setting_id = id;
1431 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1432 if ((flags & ~(kFlagsMask)) != 0) {
1433 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1438 // Validation succeeded. Pass on to visitor.
1439 visitor_->OnSetting(id, flags, value);
1443 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1444 size_t original_len = len;
1445 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1446 remaining_data_length_);
1447 remaining_data_length_ -= bytes_read;
1448 if (remaining_data_length_ == 0) {
1449 SpdyFrameReader reader(current_frame_buffer_.get(),
1450 current_frame_buffer_length_);
1451 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1453 // Use frame-specific handlers.
1454 switch (current_frame_type_) {
1456 // TODO(jgraettinger): Leaving this here for future, saner patching.
1457 // RST_STREAM is separately handled by ProcessRstStreamFramePayload().
1460 /*!FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1461 bool successful_read = true;
1462 if (spdy_version_ < 4) {
1463 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1464 DCHECK(successful_read);
1466 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1467 uint32 status_raw = status;
1468 successful_read = reader.ReadUInt32(&status_raw);
1469 DCHECK(successful_read);
1470 if (status_raw > RST_STREAM_INVALID &&
1471 status_raw < RST_STREAM_NUM_STATUS_CODES) {
1472 status = static_cast<SpdyRstStreamStatus>(status_raw);
1474 // TODO(hkhalil): Probably best to OnError here, depending on
1475 // our interpretation of the spec. Keeping with existing liberal
1476 // behavior for now.
1478 DCHECK(reader.IsDoneReading());
1479 visitor_->OnRstStream(current_frame_stream_id_, status);
1484 bool successful_read = true;
1485 if (spdy_version_ < 4) {
1487 successful_read = reader.ReadUInt32(&id32);
1490 successful_read = reader.ReadUInt64(&id);
1492 DCHECK(successful_read);
1493 DCHECK(reader.IsDoneReading());
1494 visitor_->OnPing(id);
1497 case WINDOW_UPDATE: {
1498 uint32 delta_window_size = 0;
1499 bool successful_read = true;
1500 if (spdy_version_ < 4) {
1501 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1502 DCHECK(successful_read);
1504 successful_read = reader.ReadUInt32(&delta_window_size);
1505 DCHECK(successful_read);
1506 DCHECK(reader.IsDoneReading());
1507 visitor_->OnWindowUpdate(current_frame_stream_id_,
1512 DCHECK_LE(4, protocol_version());
1513 DCHECK(reader.IsDoneReading());
1514 visitor_->OnBlocked(current_frame_stream_id_);
1519 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1522 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1524 return original_len - len;
1527 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1531 // Clamp to the actual remaining payload.
1532 if (len > remaining_data_length_) {
1533 len = remaining_data_length_;
1535 size_t original_len = len;
1537 // Check if we had already read enough bytes to parse the GOAWAY header.
1538 const size_t header_size = GetGoAwayMinimumSize();
1539 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1540 bool already_parsed_header = (unread_header_bytes == 0);
1541 if (!already_parsed_header) {
1542 // Buffer the new GOAWAY header bytes we got.
1543 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1545 // Do we have enough to parse the constant size GOAWAY header?
1546 if (current_frame_buffer_length_ == header_size) {
1547 // Parse out the last good stream id.
1548 SpdyFrameReader reader(current_frame_buffer_.get(),
1549 current_frame_buffer_length_);
1550 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1551 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1552 DCHECK(successful_read);
1554 // In SPDYv3 and up, frames also specify a status code - parse it out.
1555 SpdyGoAwayStatus status = GOAWAY_OK;
1556 if (spdy_version_ >= 3) {
1557 uint32 status_raw = GOAWAY_OK;
1558 successful_read = reader.ReadUInt32(&status_raw);
1559 DCHECK(successful_read);
1560 // We've read an unsigned integer, so it's enough to only check
1561 // upper bound to ensure the value is in valid range.
1562 if (status_raw < GOAWAY_NUM_STATUS_CODES) {
1563 status = static_cast<SpdyGoAwayStatus>(status_raw);
1565 // TODO(hkhalil): Probably best to OnError here, depending on
1566 // our interpretation of the spec. Keeping with existing liberal
1567 // behavior for now.
1571 // Finished parsing the GOAWAY header, call frame handler.
1572 visitor_->OnGoAway(current_frame_stream_id_, status);
1576 // Handle remaining data as opaque.
1577 bool processed_successfully = true;
1579 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1581 remaining_data_length_ -= original_len;
1582 if (!processed_successfully) {
1583 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1584 } else if (remaining_data_length_ == 0) {
1585 // Signal that there is not more opaque data.
1586 visitor_->OnGoAwayFrameData(NULL, 0);
1587 CHANGE_STATE(SPDY_AUTO_RESET);
1589 return original_len;
1592 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1596 // Clamp to the actual remaining payload.
1597 if (len > remaining_data_length_) {
1598 len = remaining_data_length_;
1600 size_t original_len = len;
1602 // Check if we had already read enough bytes to parse the fixed-length portion
1603 // of the RST_STREAM frame.
1604 const size_t header_size = GetRstStreamMinimumSize();
1605 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1606 bool already_parsed_header = (unread_header_bytes == 0);
1607 if (!already_parsed_header) {
1608 // Buffer the new RST_STREAM header bytes we got.
1609 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1611 // Do we have enough to parse the constant size RST_STREAM header?
1612 if (current_frame_buffer_length_ == header_size) {
1613 // Parse out the last good stream id.
1614 SpdyFrameReader reader(current_frame_buffer_.get(),
1615 current_frame_buffer_length_);
1616 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1617 if (protocol_version() < 4) {
1618 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1619 DCHECK(successful_read);
1622 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1623 uint32 status_raw = status;
1624 bool successful_read = reader.ReadUInt32(&status_raw);
1625 DCHECK(successful_read);
1626 // We've read an unsigned integer, so it's enough to only check
1627 // upper bound to ensure the value is in valid range.
1628 if (status_raw > RST_STREAM_INVALID &&
1629 status_raw < RST_STREAM_NUM_STATUS_CODES) {
1630 status = static_cast<SpdyRstStreamStatus>(status_raw);
1632 // TODO(hkhalil): Probably best to OnError here, depending on
1633 // our interpretation of the spec. Keeping with existing liberal
1634 // behavior for now.
1636 // Finished parsing the RST_STREAM header, call frame handler.
1637 visitor_->OnRstStream(current_frame_stream_id_, status);
1641 // Handle remaining data as opaque.
1642 bool processed_successfully = true;
1644 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
1646 remaining_data_length_ -= original_len;
1647 if (!processed_successfully) {
1648 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
1649 } else if (remaining_data_length_ == 0) {
1650 // Signal that there is not more opaque data.
1651 visitor_->OnRstStreamFrameData(NULL, 0);
1652 CHANGE_STATE(SPDY_AUTO_RESET);
1654 return original_len;
1657 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
1658 size_t original_len = len;
1660 if (remaining_data_length_ > 0) {
1661 size_t amount_to_forward = std::min(remaining_data_length_, len);
1662 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
1663 // Only inform the visitor if there is data.
1664 if (amount_to_forward) {
1665 visitor_->OnStreamFrameData(
1666 current_frame_stream_id_, data, amount_to_forward, false);
1669 data += amount_to_forward;
1670 len -= amount_to_forward;
1671 remaining_data_length_ -= amount_to_forward;
1673 // If the FIN flag is set, and there is no more data in this data
1674 // frame, inform the visitor of EOF via a 0-length data frame.
1675 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
1676 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1680 if (remaining_data_length_ == 0) {
1681 CHANGE_STATE(SPDY_AUTO_RESET);
1683 return original_len - len;
1686 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
1687 size_t header_length,
1688 SpdyHeaderBlock* block) const {
1689 SpdyFrameReader reader(header_data, header_length);
1691 // Read number of headers.
1693 if (spdy_version_ < 3) {
1695 if (!reader.ReadUInt16(&temp)) {
1696 DVLOG(1) << "Unable to read number of headers.";
1701 if (!reader.ReadUInt32(&num_headers)) {
1702 DVLOG(1) << "Unable to read number of headers.";
1707 // Read each header.
1708 for (uint32 index = 0; index < num_headers; ++index) {
1709 base::StringPiece temp;
1711 // Read header name.
1712 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1713 : !reader.ReadStringPiece32(&temp)) {
1714 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
1715 << num_headers << ").";
1718 std::string name = temp.as_string();
1720 // Read header value.
1721 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1722 : !reader.ReadStringPiece32(&temp)) {
1723 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
1724 << num_headers << ").";
1727 std::string value = temp.as_string();
1729 // Ensure no duplicates.
1730 if (block->find(name) != block->end()) {
1731 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
1732 << num_headers << ").";
1737 (*block)[name] = value;
1739 return reader.GetBytesConsumed();
1742 SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
1743 const size_t kSize = GetDataFrameMinimumSize() + data.data().length();
1745 SpdyDataFlags flags = DATA_FLAG_NONE;
1747 flags = DATA_FLAG_FIN;
1750 SpdyFrameBuilder builder(kSize);
1751 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1752 builder.WriteBytes(data.data().data(), data.data().length());
1753 DCHECK_EQ(kSize, builder.length());
1754 return builder.take();
1757 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
1758 const SpdyDataIR& data) const {
1759 const size_t kSize = GetDataFrameMinimumSize();
1761 SpdyDataFlags flags = DATA_FLAG_NONE;
1763 flags = DATA_FLAG_FIN;
1766 SpdyFrameBuilder builder(kSize);
1767 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1768 if (protocol_version() < 4) {
1769 builder.OverwriteLength(*this, data.data().length());
1771 builder.OverwriteLength(*this, data.data().length() + kSize);
1773 DCHECK_EQ(kSize, builder.length());
1774 return builder.take();
1777 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
1778 const SpdySynStreamIR& syn_stream) {
1780 if (syn_stream.fin()) {
1781 flags |= CONTROL_FLAG_FIN;
1783 if (syn_stream.unidirectional()) {
1784 // TODO(hkhalil): invalid for HTTP2.
1785 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
1787 if (spdy_version_ >= 4) {
1788 flags |= HEADERS_FLAG_PRIORITY;
1791 // Sanitize priority.
1792 uint8 priority = syn_stream.priority();
1793 if (priority > GetLowestPriority()) {
1794 DLOG(DFATAL) << "Priority out-of-bounds.";
1795 priority = GetLowestPriority();
1798 // The size of this frame, including variable-length name-value block.
1799 const size_t size = GetSynStreamMinimumSize()
1800 + GetSerializedLength(syn_stream.name_value_block());
1802 SpdyFrameBuilder builder(size);
1803 if (spdy_version_ < 4) {
1804 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
1805 builder.WriteUInt32(syn_stream.stream_id());
1806 builder.WriteUInt32(syn_stream.associated_to_stream_id());
1807 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
1808 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
1810 builder.WriteFramePrefix(*this,
1813 syn_stream.stream_id());
1814 builder.WriteUInt32(priority);
1816 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
1817 SerializeNameValueBlock(&builder, syn_stream);
1819 if (debug_visitor_) {
1820 const size_t payload_len = GetSerializedLength(
1821 protocol_version(), &(syn_stream.name_value_block()));
1822 // SPDY 4 reports this compression as a SYN_STREAM compression.
1823 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
1829 return builder.take();
1832 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
1833 const SpdySynReplyIR& syn_reply) {
1835 if (syn_reply.fin()) {
1836 flags |= CONTROL_FLAG_FIN;
1839 // The size of this frame, including variable-length name-value block.
1840 size_t size = GetSynReplyMinimumSize()
1841 + GetSerializedLength(syn_reply.name_value_block());
1843 SpdyFrameBuilder builder(size);
1844 if (spdy_version_ < 4) {
1845 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
1846 builder.WriteUInt32(syn_reply.stream_id());
1848 builder.WriteFramePrefix(*this,
1851 syn_reply.stream_id());
1853 if (protocol_version() < 3) {
1854 builder.WriteUInt16(0); // Unused.
1856 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
1857 SerializeNameValueBlock(&builder, syn_reply);
1859 if (debug_visitor_) {
1860 const size_t payload_len = GetSerializedLength(
1861 protocol_version(), &(syn_reply.name_value_block()));
1862 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
1868 return builder.take();
1871 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
1872 const SpdyRstStreamIR& rst_stream) const {
1873 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
1874 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
1875 // which doesn't currently include RST_STREAM payloads. GFE flags have been
1876 // commented but left in place to simplify future patching.
1877 // Compute the output buffer size, taking opaque data into account.
1878 uint16 expected_length = GetRstStreamMinimumSize();
1879 if (protocol_version() >= 4 &&
1880 false /*FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1881 expected_length += rst_stream.description().size();
1883 SpdyFrameBuilder builder(expected_length);
1885 // Serialize the RST_STREAM frame.
1886 if (protocol_version() < 4) {
1887 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
1888 builder.WriteUInt32(rst_stream.stream_id());
1890 builder.WriteFramePrefix(*this, RST_STREAM, 0, rst_stream.stream_id());
1893 builder.WriteUInt32(rst_stream.status());
1895 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
1896 if (protocol_version() >= 4 && rst_stream.description().size() > 0 &&
1897 false /*FLAGS_gfe2_restart_flag_allow_spdy_4_rst_stream_opaque_data*/) {
1898 builder.WriteBytes(rst_stream.description().data(),
1899 rst_stream.description().size());
1902 DCHECK_EQ(expected_length, builder.length());
1903 return builder.take();
1906 SpdySerializedFrame* SpdyFramer::SerializeSettings(
1907 const SpdySettingsIR& settings) const {
1909 if (settings.clear_settings()) {
1910 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1912 const SpdySettingsIR::ValueMap* values = &(settings.values());
1914 // Size, in bytes, of this SETTINGS frame.
1915 const size_t size = GetSettingsMinimumSize() + (values->size() * 8);
1917 SpdyFrameBuilder builder(size);
1918 if (spdy_version_ < 4) {
1919 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
1921 builder.WriteFramePrefix(*this, SETTINGS, flags, 0);
1923 builder.WriteUInt32(values->size());
1924 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
1925 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
1926 it != values->end();
1928 uint8 setting_flags = 0;
1929 if (it->second.persist_value) {
1930 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
1932 if (it->second.persisted) {
1933 setting_flags |= SETTINGS_FLAG_PERSISTED;
1935 SettingsFlagsAndId flags_and_id(setting_flags, it->first);
1936 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
1937 builder.WriteBytes(&id_and_flags_wire, 4);
1938 builder.WriteUInt32(it->second.value);
1940 DCHECK_EQ(size, builder.length());
1941 return builder.take();
1944 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
1945 DCHECK_LE(4, protocol_version());
1946 SpdyFrameBuilder builder(GetBlockedSize());
1947 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id());
1948 return builder.take();
1951 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
1952 SpdyFrameBuilder builder(GetPingSize());
1953 if (spdy_version_ < 4) {
1954 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
1955 builder.WriteUInt32(static_cast<uint32>(ping.id()));
1957 builder.WriteFramePrefix(*this, PING, 0, 0);
1958 builder.WriteUInt64(ping.id());
1960 DCHECK_EQ(GetPingSize(), builder.length());
1961 return builder.take();
1964 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
1965 const SpdyGoAwayIR& goaway) const {
1967 // Compute the output buffer size, take opaque data into account.
1968 uint16 expected_length = GetGoAwayMinimumSize();
1969 if (protocol_version() >= 4) {
1970 expected_length += goaway.description().size();
1972 SpdyFrameBuilder builder(expected_length);
1974 // Serialize the GOAWAY frame.
1975 if (spdy_version_ < 4) {
1976 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
1978 builder.WriteFramePrefix(*this, GOAWAY, 0, 0);
1981 // GOAWAY frames specify the last good stream id for all SPDY versions.
1982 builder.WriteUInt32(goaway.last_good_stream_id());
1984 // In SPDY3 and up, GOAWAY frames also specify the error status code.
1985 if (protocol_version() >= 3) {
1986 builder.WriteUInt32(goaway.status());
1989 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
1990 if ((protocol_version() >= 4) && (goaway.description().size() > 0)) {
1991 builder.WriteBytes(goaway.description().data(),
1992 goaway.description().size());
1995 DCHECK_EQ(expected_length, builder.length());
1996 return builder.take();
1999 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2000 const SpdyHeadersIR& headers) {
2002 if (headers.fin()) {
2003 flags |= CONTROL_FLAG_FIN;
2006 // The size of this frame, including variable-length name-value block.
2007 size_t size = GetHeadersMinimumSize()
2008 + GetSerializedLength(headers.name_value_block());
2010 SpdyFrameBuilder builder(size);
2011 if (spdy_version_ < 4) {
2012 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2013 builder.WriteUInt32(headers.stream_id());
2015 builder.WriteFramePrefix(*this,
2018 headers.stream_id());
2020 if (protocol_version() < 3) {
2021 builder.WriteUInt16(0); // Unused.
2023 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2025 SerializeNameValueBlock(&builder, headers);
2027 if (debug_visitor_) {
2028 const size_t payload_len = GetSerializedLength(
2029 protocol_version(), &(headers.name_value_block()));
2030 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2036 return builder.take();
2039 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2040 const SpdyWindowUpdateIR& window_update) const {
2041 SpdyFrameBuilder builder(GetWindowUpdateSize());
2042 if (spdy_version_ < 4) {
2043 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2044 builder.WriteUInt32(window_update.stream_id());
2046 builder.WriteFramePrefix(*this,
2049 window_update.stream_id());
2051 builder.WriteUInt32(window_update.delta());
2052 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2053 return builder.take();
2056 SpdyFrame* SpdyFramer::SerializePushPromise(
2057 const SpdyPushPromiseIR& push_promise) {
2058 DCHECK_LE(4, protocol_version());
2059 // The size of this frame, including variable-length name-value block.
2060 size_t size = GetPushPromiseMinimumSize()
2061 + GetSerializedLength(push_promise.name_value_block());
2063 SpdyFrameBuilder builder(size);
2064 builder.WriteFramePrefix(*this, PUSH_PROMISE, kNoFlags,
2065 push_promise.stream_id());
2066 builder.WriteUInt32(push_promise.promised_stream_id());
2067 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2069 SerializeNameValueBlock(&builder, push_promise);
2071 if (debug_visitor_) {
2072 const size_t payload_len = GetSerializedLength(
2073 protocol_version(), &(push_promise.name_value_block()));
2074 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2075 PUSH_PROMISE, payload_len, builder.length());
2078 return builder.take();
2083 class FrameSerializationVisitor : public SpdyFrameVisitor {
2085 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2086 virtual ~FrameSerializationVisitor() {}
2088 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2090 virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2091 frame_.reset(framer_->SerializeData(data));
2093 virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2094 frame_.reset(framer_->SerializeSynStream(syn_stream));
2096 virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2097 frame_.reset(framer_->SerializeSynReply(syn_reply));
2099 virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2100 frame_.reset(framer_->SerializeRstStream(rst_stream));
2102 virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2103 frame_.reset(framer_->SerializeSettings(settings));
2105 virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2106 frame_.reset(framer_->SerializePing(ping));
2108 virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2109 frame_.reset(framer_->SerializeGoAway(goaway));
2111 virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2112 frame_.reset(framer_->SerializeHeaders(headers));
2114 virtual void VisitWindowUpdate(
2115 const SpdyWindowUpdateIR& window_update) OVERRIDE {
2116 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2118 virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2119 frame_.reset(framer_->SerializeBlocked(blocked));
2121 virtual void VisitPushPromise(
2122 const SpdyPushPromiseIR& push_promise) OVERRIDE {
2123 frame_.reset(framer_->SerializePushPromise(push_promise));
2127 SpdyFramer* framer_;
2128 scoped_ptr<SpdySerializedFrame> frame_;
2133 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2134 FrameSerializationVisitor visitor(this);
2135 frame.Visit(&visitor);
2136 return visitor.ReleaseSerializedFrame();
2139 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2140 const size_t uncompressed_length =
2141 GetSerializedLength(protocol_version(), &headers);
2142 if (!enable_compression_) {
2143 return uncompressed_length;
2145 z_stream* compressor = GetHeaderCompressor();
2146 // Since we'll be performing lots of flushes when compressing the data,
2147 // zlib's lower bounds may be insufficient.
2148 return 2 * deflateBound(compressor, uncompressed_length);
2151 // The following compression setting are based on Brian Olson's analysis. See
2152 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2153 // for more details.
2154 #if defined(USE_SYSTEM_ZLIB)
2155 // System zlib is not expected to have workaround for http://crbug.com/139744,
2156 // so disable compression in that case.
2157 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2158 static const int kCompressorLevel = 0;
2159 #else // !defined(USE_SYSTEM_ZLIB)
2160 static const int kCompressorLevel = 9;
2161 #endif // !defined(USE_SYSTEM_ZLIB)
2162 static const int kCompressorWindowSizeInBits = 11;
2163 static const int kCompressorMemLevel = 1;
2165 z_stream* SpdyFramer::GetHeaderCompressor() {
2166 if (header_compressor_.get())
2167 return header_compressor_.get(); // Already initialized.
2169 header_compressor_.reset(new z_stream);
2170 memset(header_compressor_.get(), 0, sizeof(z_stream));
2172 int success = deflateInit2(header_compressor_.get(),
2175 kCompressorWindowSizeInBits,
2176 kCompressorMemLevel,
2177 Z_DEFAULT_STRATEGY);
2178 if (success == Z_OK) {
2179 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2181 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2182 : kV3DictionarySize;
2183 success = deflateSetDictionary(header_compressor_.get(),
2184 reinterpret_cast<const Bytef*>(dictionary),
2187 if (success != Z_OK) {
2188 LOG(WARNING) << "deflateSetDictionary failure: " << success;
2189 header_compressor_.reset(NULL);
2192 return header_compressor_.get();
2195 z_stream* SpdyFramer::GetHeaderDecompressor() {
2196 if (header_decompressor_.get())
2197 return header_decompressor_.get(); // Already initialized.
2199 header_decompressor_.reset(new z_stream);
2200 memset(header_decompressor_.get(), 0, sizeof(z_stream));
2202 int success = inflateInit(header_decompressor_.get());
2203 if (success != Z_OK) {
2204 LOG(WARNING) << "inflateInit failure: " << success;
2205 header_decompressor_.reset(NULL);
2208 return header_decompressor_.get();
2211 // Incrementally decompress the control frame's header block, feeding the
2212 // result to the visitor in chunks. Continue this until the visitor
2213 // indicates that it cannot process any more data, or (more commonly) we
2214 // run out of data to deliver.
2215 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
2216 SpdyStreamId stream_id,
2219 // Get a decompressor or set error.
2220 z_stream* decomp = GetHeaderDecompressor();
2221 if (decomp == NULL) {
2222 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
2223 set_error(SPDY_DECOMPRESS_FAILURE);
2227 bool processed_successfully = true;
2228 char buffer[kHeaderDataChunkMaxSize];
2230 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
2231 decomp->avail_in = len;
2232 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
2233 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
2234 // reached this method successfully, stream_id should be nonzero.
2235 DCHECK_LT(0u, stream_id);
2236 while (decomp->avail_in > 0 && processed_successfully) {
2237 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
2238 decomp->avail_out = arraysize(buffer);
2240 int rv = inflate(decomp, Z_SYNC_FLUSH);
2241 if (rv == Z_NEED_DICT) {
2242 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2244 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2245 : kV3DictionarySize;
2246 const DictionaryIds& ids = g_dictionary_ids.Get();
2247 const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
2248 : ids.v3_dictionary_id;
2249 // Need to try again with the right dictionary.
2250 if (decomp->adler == dictionary_id) {
2251 rv = inflateSetDictionary(decomp,
2252 reinterpret_cast<const Bytef*>(dictionary),
2255 rv = inflate(decomp, Z_SYNC_FLUSH);
2259 // Inflate will generate a Z_BUF_ERROR if it runs out of input
2260 // without producing any output. The input is consumed and
2261 // buffered internally by zlib so we can detect this condition by
2262 // checking if avail_in is 0 after the call to inflate.
2263 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
2264 if ((rv == Z_OK) || input_exhausted) {
2265 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
2266 if (decompressed_len > 0) {
2267 processed_successfully = visitor_->OnControlFrameHeaderData(
2268 stream_id, buffer, decompressed_len);
2270 if (!processed_successfully) {
2271 // Assume that the problem was the header block was too large for the
2273 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2276 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
2277 set_error(SPDY_DECOMPRESS_FAILURE);
2278 processed_successfully = false;
2281 return processed_successfully;
2284 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
2285 SpdyStreamId stream_id, const char* data, size_t len) {
2286 bool read_successfully = true;
2287 while (read_successfully && len > 0) {
2288 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
2289 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
2291 data += bytes_to_deliver;
2292 len -= bytes_to_deliver;
2293 if (!read_successfully) {
2294 // Assume that the problem was the header block was too large for the
2296 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2299 return read_successfully;
2302 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
2303 SpdyFrameBuilder* builder,
2304 const SpdyNameValueBlock& name_value_block) const {
2305 // Serialize number of headers.
2306 if (protocol_version() < 3) {
2307 builder->WriteUInt16(name_value_block.size());
2309 builder->WriteUInt32(name_value_block.size());
2312 // Serialize each header.
2313 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
2314 it != name_value_block.end();
2316 if (protocol_version() < 3) {
2317 builder->WriteString(it->first);
2318 builder->WriteString(it->second);
2320 builder->WriteStringPiece32(it->first);
2321 builder->WriteStringPiece32(it->second);
2326 void SpdyFramer::SerializeNameValueBlock(
2327 SpdyFrameBuilder* builder,
2328 const SpdyFrameWithNameValueBlockIR& frame) {
2329 if (!enable_compression_) {
2330 return SerializeNameValueBlockWithoutCompression(builder,
2331 frame.name_value_block());
2334 // First build an uncompressed version to be fed into the compressor.
2335 const size_t uncompressed_len = GetSerializedLength(
2336 protocol_version(), &(frame.name_value_block()));
2337 SpdyFrameBuilder uncompressed_builder(uncompressed_len);
2338 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
2339 frame.name_value_block());
2340 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
2342 z_stream* compressor = GetHeaderCompressor();
2344 LOG(DFATAL) << "Could not obtain compressor.";
2348 base::StatsCounter compressed_frames("spdy.CompressedFrames");
2349 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
2350 base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
2352 // Create an output frame.
2353 // Since we'll be performing lots of flushes when compressing the data,
2354 // zlib's lower bounds may be insufficient.
2356 // TODO(akalin): Avoid the duplicate calculation with
2357 // GetSerializedLength(const SpdyHeaderBlock&).
2358 const int compressed_max_size =
2359 2 * deflateBound(compressor, uncompressed_len);
2361 // TODO(phajdan.jr): Clean up after we no longer need
2362 // to workaround http://crbug.com/139744.
2363 #if defined(USE_SYSTEM_ZLIB)
2364 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
2365 compressor->avail_in = uncompressed_len;
2366 #endif // defined(USE_SYSTEM_ZLIB)
2367 compressor->next_out = reinterpret_cast<Bytef*>(
2368 builder->GetWritableBuffer(compressed_max_size));
2369 compressor->avail_out = compressed_max_size;
2371 // TODO(phajdan.jr): Clean up after we no longer need
2372 // to workaround http://crbug.com/139744.
2373 #if defined(USE_SYSTEM_ZLIB)
2374 int rv = deflate(compressor, Z_SYNC_FLUSH);
2375 if (rv != Z_OK) { // How can we know that it compressed everything?
2376 // This shouldn't happen, right?
2377 LOG(WARNING) << "deflate failure: " << rv;
2378 // TODO(akalin): Upstream this return.
2382 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
2383 #endif // defined(USE_SYSTEM_ZLIB)
2385 int compressed_size = compressed_max_size - compressor->avail_out;
2386 builder->Seek(compressed_size);
2387 builder->RewriteLength(*this);
2389 pre_compress_bytes.Add(uncompressed_len);
2390 post_compress_bytes.Add(compressed_size);
2392 compressed_frames.Increment();