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 LOG(INFO) << "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 DCHECK_GT(1u << 24, id) << "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 SpdyCredential::SpdyCredential() : slot(0) {}
115 SpdyCredential::~SpdyCredential() {}
117 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
118 : current_frame_buffer_(new char[kControlFrameBufferSize]),
119 enable_compression_(true),
121 debug_visitor_(NULL),
122 display_protocol_("SPDY"),
123 spdy_version_(version),
124 syn_frame_processed_(false),
125 probable_http_response_(false) {
126 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
127 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
131 SpdyFramer::~SpdyFramer() {
132 if (header_compressor_.get()) {
133 deflateEnd(header_compressor_.get());
135 if (header_decompressor_.get()) {
136 inflateEnd(header_decompressor_.get());
140 void SpdyFramer::Reset() {
142 previous_state_ = SPDY_RESET;
143 error_code_ = SPDY_NO_ERROR;
144 remaining_data_length_ = 0;
145 remaining_control_header_ = 0;
146 current_frame_buffer_length_ = 0;
147 current_frame_type_ = DATA;
148 current_frame_flags_ = 0;
149 current_frame_length_ = 0;
150 current_frame_stream_id_ = kInvalidStream;
151 settings_scratch_.Reset();
154 size_t SpdyFramer::GetDataFrameMinimumSize() const {
155 // Size, in bytes, of the data frame header. Future versions of SPDY
156 // will likely vary this, so we allow for the flexibility of a function call
157 // for this value as opposed to a constant.
161 // Size, in bytes, of the control frame header.
162 size_t SpdyFramer::GetControlFrameHeaderSize() const {
163 switch (protocol_version()) {
169 LOG(DFATAL) << "Unhandled SPDY version.";
173 size_t SpdyFramer::GetSynStreamMinimumSize() const {
174 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
176 if (spdy_version_ < 4) {
178 // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot)
179 return GetControlFrameHeaderSize() + 10;
182 // frame prefix + 4 (associated stream ID) + 1 (priority) + 1 (slot)
183 return GetControlFrameHeaderSize() + 6;
187 size_t SpdyFramer::GetSynReplyMinimumSize() const {
188 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
190 size_t size = GetControlFrameHeaderSize();
191 if (spdy_version_ < 4) {
193 // control frame header + 4 (stream IDs)
197 // In SPDY 2, there were 2 unused bytes before payload.
198 if (protocol_version() < 3) {
205 size_t SpdyFramer::GetRstStreamSize() const {
206 // Size, in bytes, of a RST_STREAM frame.
207 if (spdy_version_ < 4) {
209 // control frame header + 4 (stream id) + 4 (status code)
210 return GetControlFrameHeaderSize() + 8;
213 // frame prefix + 4 (status code)
214 return GetControlFrameHeaderSize() + 4;
218 size_t SpdyFramer::GetSettingsMinimumSize() const {
219 // Size, in bytes, of a SETTINGS frame not including the IDs and values
220 // from the variable-length value block. Calculated as:
221 // control frame header + 4 (number of ID/value pairs)
222 return GetControlFrameHeaderSize() + 4;
225 size_t SpdyFramer::GetPingSize() const {
226 // Size, in bytes, of this PING frame. Calculated as:
227 // control frame header + 4 (id)
228 return GetControlFrameHeaderSize() + 4;
231 size_t SpdyFramer::GetGoAwaySize() const {
232 // Size, in bytes, of this GOAWAY frame. Calculated as:
233 // control frame header + 4 (last good stream id)
234 size_t size = GetControlFrameHeaderSize() + 4;
236 // SPDY 3+ GOAWAY frames also contain a status.
237 if (protocol_version() >= 3) {
244 size_t SpdyFramer::GetHeadersMinimumSize() const {
245 // Size, in bytes, of a HEADERS frame not including the variable-length
247 size_t size = GetControlFrameHeaderSize();
248 if (spdy_version_ < 4) {
250 // control frame header + 4 (stream IDs)
254 // In SPDY 2, there were 2 unused bytes before payload.
255 if (protocol_version() < 3) {
262 size_t SpdyFramer::GetWindowUpdateSize() const {
263 // Size, in bytes, of a WINDOW_UPDATE frame.
264 if (spdy_version_ < 4) {
266 // control frame header + 4 (stream id) + 4 (delta)
267 return GetControlFrameHeaderSize() + 8;
270 // frame prefix + 4 (delta)
271 return GetControlFrameHeaderSize() + 4;
275 size_t SpdyFramer::GetCredentialMinimumSize() const {
276 // Size, in bytes, of a CREDENTIAL frame sans variable-length certificate list
277 // and proof. Calculated as:
278 // control frame header + 2 (slot)
279 return GetControlFrameHeaderSize() + 2;
282 size_t SpdyFramer::GetBlockedSize() const {
283 DCHECK_LE(4, protocol_version());
284 // Size, in bytes, of a BLOCKED frame.
285 // The BLOCKED frame has no payload beyond the control frame header.
286 return GetControlFrameHeaderSize();
289 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
290 DCHECK_LE(4, protocol_version());
291 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
292 // Calculated as frame prefix + 4 (promised stream id).
293 return GetControlFrameHeaderSize() + 4;
296 size_t SpdyFramer::GetFrameMinimumSize() const {
297 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
300 size_t SpdyFramer::GetFrameMaximumSize() const {
301 return (protocol_version() < 4) ? 0xffffff : 0xffff;
304 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
305 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
308 const char* SpdyFramer::StateToString(int state) {
312 case SPDY_AUTO_RESET:
316 case SPDY_READING_COMMON_HEADER:
317 return "READING_COMMON_HEADER";
318 case SPDY_CONTROL_FRAME_PAYLOAD:
319 return "CONTROL_FRAME_PAYLOAD";
320 case SPDY_IGNORE_REMAINING_PAYLOAD:
321 return "IGNORE_REMAINING_PAYLOAD";
322 case SPDY_FORWARD_STREAM_FRAME:
323 return "FORWARD_STREAM_FRAME";
324 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
325 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
326 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
327 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
328 case SPDY_CREDENTIAL_FRAME_PAYLOAD:
329 return "SPDY_CREDENTIAL_FRAME_PAYLOAD";
330 case SPDY_SETTINGS_FRAME_PAYLOAD:
331 return "SPDY_SETTINGS_FRAME_PAYLOAD";
333 return "UNKNOWN_STATE";
336 void SpdyFramer::set_error(SpdyError error) {
339 CHANGE_STATE(SPDY_ERROR);
340 visitor_->OnError(this);
343 const char* SpdyFramer::ErrorCodeToString(int error_code) {
344 switch (error_code) {
347 case SPDY_INVALID_CONTROL_FRAME:
348 return "INVALID_CONTROL_FRAME";
349 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
350 return "CONTROL_PAYLOAD_TOO_LARGE";
351 case SPDY_ZLIB_INIT_FAILURE:
352 return "ZLIB_INIT_FAILURE";
353 case SPDY_UNSUPPORTED_VERSION:
354 return "UNSUPPORTED_VERSION";
355 case SPDY_DECOMPRESS_FAILURE:
356 return "DECOMPRESS_FAILURE";
357 case SPDY_COMPRESS_FAILURE:
358 return "COMPRESS_FAILURE";
359 case SPDY_INVALID_DATA_FRAME_FLAGS:
360 return "SPDY_INVALID_DATA_FRAME_FLAGS";
361 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
362 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
364 return "UNKNOWN_ERROR";
367 const char* SpdyFramer::StatusCodeToString(int status_code) {
368 switch (status_code) {
369 case RST_STREAM_INVALID:
371 case RST_STREAM_PROTOCOL_ERROR:
372 return "PROTOCOL_ERROR";
373 case RST_STREAM_INVALID_STREAM:
374 return "INVALID_STREAM";
375 case RST_STREAM_REFUSED_STREAM:
376 return "REFUSED_STREAM";
377 case RST_STREAM_UNSUPPORTED_VERSION:
378 return "UNSUPPORTED_VERSION";
379 case RST_STREAM_CANCEL:
381 case RST_STREAM_INTERNAL_ERROR:
382 return "INTERNAL_ERROR";
383 case RST_STREAM_FLOW_CONTROL_ERROR:
384 return "FLOW_CONTROL_ERROR";
385 case RST_STREAM_STREAM_IN_USE:
386 return "STREAM_IN_USE";
387 case RST_STREAM_STREAM_ALREADY_CLOSED:
388 return "STREAM_ALREADY_CLOSED";
389 case RST_STREAM_INVALID_CREDENTIALS:
390 return "INVALID_CREDENTIALS";
391 case RST_STREAM_FRAME_TOO_LARGE:
392 return "FRAME_TOO_LARGE";
394 return "UNKNOWN_STATUS";
397 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
418 return "WINDOW_UPDATE";
424 return "PUSH_PROMISE";
426 return "UNKNOWN_CONTROL_TYPE";
429 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
433 size_t original_len = len;
435 previous_state_ = state_;
440 case SPDY_AUTO_RESET:
444 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
448 case SPDY_READING_COMMON_HEADER: {
449 size_t bytes_read = ProcessCommonHeader(data, len);
455 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
456 // Control frames that contain header blocks
457 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE)
458 // take a different path through the state machine - they
460 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
461 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
463 // SETTINGS frames take a slightly modified route:
464 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
465 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
467 // All other control frames will use the alternate route directly to
468 // SPDY_CONTROL_FRAME_PAYLOAD
469 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
475 case SPDY_SETTINGS_FRAME_PAYLOAD: {
476 int bytes_read = ProcessSettingsFramePayload(data, len);
482 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
483 int bytes_read = ProcessControlFrameHeaderBlock(data, len);
489 case SPDY_CREDENTIAL_FRAME_PAYLOAD: {
490 size_t bytes_read = ProcessCredentialFramePayload(data, len);
496 case SPDY_CONTROL_FRAME_PAYLOAD: {
497 size_t bytes_read = ProcessControlFramePayload(data, len);
503 case SPDY_IGNORE_REMAINING_PAYLOAD:
504 // control frame has too-large payload
505 // intentional fallthrough
506 case SPDY_FORWARD_STREAM_FRAME: {
507 size_t bytes_read = ProcessDataFramePayload(data, len);
513 LOG(DFATAL) << "Invalid value for " << display_protocol_
514 << " framer state: " << state_;
515 // This ensures that we don't infinite-loop if state_ gets an
516 // invalid value somehow, such as due to a SpdyFramer getting deleted
517 // from a callback it calls.
520 } while (state_ != previous_state_);
522 DCHECK(len == 0 || state_ == SPDY_ERROR);
523 if (current_frame_buffer_length_ == 0 &&
524 remaining_data_length_ == 0 &&
525 remaining_control_header_ == 0) {
526 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
527 << "State: " << StateToString(state_);
530 return original_len - len;
533 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
534 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
536 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
538 size_t original_len = len;
540 // Update current frame buffer as needed.
541 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
542 size_t bytes_desired =
543 GetControlFrameHeaderSize() - current_frame_buffer_length_;
544 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
547 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
548 // Not enough information to do anything meaningful.
549 return original_len - len;
552 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
553 // when processing DATA frames below.
554 scoped_ptr<SpdyFrameReader> reader(
555 new SpdyFrameReader(current_frame_buffer_.get(),
556 current_frame_buffer_length_));
559 bool is_control_frame = false;
561 uint16 control_frame_type_field = DATA;
562 // ProcessControlFrameHeader() will set current_frame_type_ to the
563 // correct value if this is a valid control frame.
564 current_frame_type_ = DATA;
565 if (protocol_version() < 4) {
566 bool successful_read = reader->ReadUInt16(&version);
567 DCHECK(successful_read);
568 is_control_frame = (version & kControlFlagMask) != 0;
569 version &= ~kControlFlagMask; // Only valid for control frames.
571 if (is_control_frame) {
572 // We check control_frame_type_field's validity in
573 // ProcessControlFrameHeader().
574 successful_read = reader->ReadUInt16(&control_frame_type_field);
577 successful_read = reader->ReadUInt31(¤t_frame_stream_id_);
579 DCHECK(successful_read);
581 successful_read = reader->ReadUInt8(¤t_frame_flags_);
582 DCHECK(successful_read);
584 uint32 length_field = 0;
585 successful_read = reader->ReadUInt24(&length_field);
586 DCHECK(successful_read);
587 remaining_data_length_ = length_field;
588 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
590 version = protocol_version();
591 uint16 length_field = 0;
592 bool successful_read = reader->ReadUInt16(&length_field);
593 DCHECK(successful_read);
594 current_frame_length_ = length_field;
596 uint8 control_frame_type_field_uint8 = DATA;
597 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
598 DCHECK(successful_read);
599 // We check control_frame_type_field's validity in
600 // ProcessControlFrameHeader().
601 control_frame_type_field = control_frame_type_field_uint8;
602 is_control_frame = (control_frame_type_field != DATA);
604 successful_read = reader->ReadUInt8(¤t_frame_flags_);
605 DCHECK(successful_read);
607 successful_read = reader->ReadUInt31(¤t_frame_stream_id_);
608 DCHECK(successful_read);
610 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
612 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
613 : GetDataFrameMinimumSize(),
614 reader->GetBytesConsumed());
615 DCHECK_EQ(current_frame_length_,
616 remaining_data_length_ + reader->GetBytesConsumed());
618 // This is just a sanity check for help debugging early frame errors.
619 if (remaining_data_length_ > 1000000u) {
620 // The strncmp for 5 is safe because we only hit this point if we
621 // have kMinCommonHeader (8) bytes
622 if (!syn_frame_processed_ &&
623 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
624 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
626 probable_http_response_ = true;
628 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
629 << " session is likely corrupt.";
633 // if we're here, then we have the common header all received.
634 if (!is_control_frame) {
635 if (current_frame_flags_ & ~DATA_FLAG_FIN) {
636 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
638 visitor_->OnDataFrameHeader(current_frame_stream_id_,
639 remaining_data_length_,
640 current_frame_flags_ & DATA_FLAG_FIN);
641 if (remaining_data_length_ > 0) {
642 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
645 if (current_frame_flags_ & DATA_FLAG_FIN) {
646 visitor_->OnStreamFrameData(
647 current_frame_stream_id_, NULL, 0, true);
649 CHANGE_STATE(SPDY_AUTO_RESET);
652 } else if (version != spdy_version_) {
653 // We check version before we check validity: version can never be
654 // 'invalid', it can only be unsupported.
655 DLOG(INFO) << "Unsupported SPDY version " << version
656 << " (expected " << spdy_version_ << ")";
657 set_error(SPDY_UNSUPPORTED_VERSION);
659 ProcessControlFrameHeader(control_frame_type_field);
662 return original_len - len;
665 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
666 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
667 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
669 if (control_frame_type_field < FIRST_CONTROL_TYPE ||
670 control_frame_type_field > LAST_CONTROL_TYPE) {
671 set_error(SPDY_INVALID_CONTROL_FRAME);
675 current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
677 if (current_frame_type_ == NOOP) {
678 DLOG(INFO) << "NOOP control frame found. Ignoring.";
679 CHANGE_STATE(SPDY_AUTO_RESET);
683 // Do some sanity checking on the control frame sizes and flags.
684 switch (current_frame_type_) {
686 if (current_frame_length_ < GetSynStreamMinimumSize()) {
687 set_error(SPDY_INVALID_CONTROL_FRAME);
688 } else if (current_frame_flags_ &
689 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
690 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
694 if (current_frame_length_ < GetSynReplyMinimumSize()) {
695 set_error(SPDY_INVALID_CONTROL_FRAME);
696 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
697 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
701 if (current_frame_length_ != GetRstStreamSize()) {
702 set_error(SPDY_INVALID_CONTROL_FRAME);
703 } else if (current_frame_flags_ != 0) {
704 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
708 // Make sure that we have an integral number of 8-byte key/value pairs,
709 // plus a 4-byte length field.
710 if (current_frame_length_ < GetSettingsMinimumSize() ||
711 (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) {
712 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
713 << current_frame_length_;
714 set_error(SPDY_INVALID_CONTROL_FRAME);
715 } else if (current_frame_flags_ &
716 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
717 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
721 if (current_frame_length_ != GetPingSize()) {
722 set_error(SPDY_INVALID_CONTROL_FRAME);
723 } else if (current_frame_flags_ != 0) {
724 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
729 if (current_frame_length_ != GetGoAwaySize()) {
730 set_error(SPDY_INVALID_CONTROL_FRAME);
731 } else if (current_frame_flags_ != 0) {
732 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
737 if (current_frame_length_ < GetHeadersMinimumSize()) {
738 set_error(SPDY_INVALID_CONTROL_FRAME);
739 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
740 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
744 if (current_frame_length_ != GetWindowUpdateSize()) {
745 set_error(SPDY_INVALID_CONTROL_FRAME);
746 } else if (current_frame_flags_ != 0) {
747 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
751 if (current_frame_length_ < GetCredentialMinimumSize()) {
752 set_error(SPDY_INVALID_CONTROL_FRAME);
753 } else if (current_frame_flags_ != 0) {
754 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
758 if (current_frame_length_ != GetBlockedSize()) {
759 set_error(SPDY_INVALID_CONTROL_FRAME);
760 } else if (current_frame_flags_ != 0) {
761 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
765 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
766 set_error(SPDY_INVALID_CONTROL_FRAME);
767 } else if (current_frame_flags_ != 0) {
768 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
772 LOG(WARNING) << "Valid " << display_protocol_
773 << " control frame with unhandled type: "
774 << current_frame_type_;
775 // This branch should be unreachable because of the frame type bounds
776 // check above. However, we DLOG(FATAL) here in an effort to painfully
777 // club the head of the developer who failed to keep this file in sync
778 // with spdy_protocol.h.
780 set_error(SPDY_INVALID_CONTROL_FRAME);
784 if (state_ == SPDY_ERROR) {
788 if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
789 DLOG(WARNING) << "Received control frame with way too big of a payload: "
790 << current_frame_length_;
791 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
795 if (current_frame_type_ == CREDENTIAL) {
796 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD);
800 // Determine the frame size without variable-length data.
801 int32 frame_size_without_variable_data;
802 switch (current_frame_type_) {
804 syn_frame_processed_ = true;
805 frame_size_without_variable_data = GetSynStreamMinimumSize();
808 syn_frame_processed_ = true;
809 frame_size_without_variable_data = GetSynReplyMinimumSize();
812 frame_size_without_variable_data = GetSettingsMinimumSize();
815 frame_size_without_variable_data = GetHeadersMinimumSize();
818 frame_size_without_variable_data = GetPushPromiseMinimumSize();
821 frame_size_without_variable_data = -1;
825 if ((frame_size_without_variable_data == -1) &&
826 (current_frame_length_ > kControlFrameBufferSize)) {
827 // We should already be in an error state. Double-check.
828 DCHECK_EQ(SPDY_ERROR, state_);
829 if (state_ != SPDY_ERROR) {
830 LOG(DFATAL) << display_protocol_
831 << " control frame buffer too small for fixed-length frame.";
832 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
837 if (frame_size_without_variable_data > 0) {
838 // We have a control frame with a header block. We need to parse the
839 // remainder of the control frame's header before we can parse the header
840 // block. The start of the header block varies with the control type.
841 DCHECK_GE(frame_size_without_variable_data,
842 static_cast<int32>(current_frame_buffer_length_));
843 remaining_control_header_ = frame_size_without_variable_data -
844 current_frame_buffer_length_;
846 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
850 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
853 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
855 size_t bytes_to_read = std::min(*len, max_bytes);
856 if (bytes_to_read > 0) {
857 DCHECK_GE(kControlFrameBufferSize,
858 current_frame_buffer_length_ + bytes_to_read);
859 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
862 current_frame_buffer_length_ += bytes_to_read;
863 *data += bytes_to_read;
864 *len -= bytes_to_read;
866 return bytes_to_read;
869 size_t SpdyFramer::GetSerializedLength(const int spdy_version,
870 const SpdyHeaderBlock* headers) {
871 const size_t num_name_value_pairs_size
872 = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32);
873 const size_t length_of_name_size = num_name_value_pairs_size;
874 const size_t length_of_value_size = num_name_value_pairs_size;
876 size_t total_length = num_name_value_pairs_size;
877 for (SpdyHeaderBlock::const_iterator it = headers->begin();
878 it != headers->end();
880 // We add space for the length of the name and the length of the value as
881 // well as the length of the name and the length of the value.
882 total_length += length_of_name_size + it->first.size() +
883 length_of_value_size + it->second.size();
888 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
889 const int spdy_version,
890 const SpdyHeaderBlock* headers) {
891 if (spdy_version < 3) {
892 frame->WriteUInt16(headers->size()); // Number of headers.
894 frame->WriteUInt32(headers->size()); // Number of headers.
896 SpdyHeaderBlock::const_iterator it;
897 for (it = headers->begin(); it != headers->end(); ++it) {
898 if (spdy_version < 3) {
899 frame->WriteString(it->first);
900 frame->WriteString(it->second);
902 frame->WriteStringPiece32(it->first);
903 frame->WriteStringPiece32(it->second);
908 // TODO(phajdan.jr): Clean up after we no longer need
909 // to workaround http://crbug.com/139744.
910 #if !defined(USE_SYSTEM_ZLIB)
912 // These constants are used by zlib to differentiate between normal data and
913 // cookie data. Cookie data is handled specially by zlib when compressing.
915 // kZStandardData is compressed normally, save that it will never match
916 // against any other class of data in the window.
917 kZStandardData = Z_CLASS_STANDARD,
918 // kZCookieData is compressed in its own Huffman blocks and only matches in
919 // its entirety and only against other kZCookieData blocks. Any matches must
920 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
921 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
923 kZCookieData = Z_CLASS_COOKIE,
924 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
925 // against the window.
926 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
929 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
930 // needed when switching between classes of data.
931 static void WriteZ(const base::StringPiece& data,
936 // If we are switching from standard to non-standard data then we need to end
937 // the current Huffman context to avoid it leaking between them.
938 if (out->clas == kZStandardData &&
939 clas != kZStandardData) {
941 rv = deflate(out, Z_PARTIAL_FLUSH);
943 DCHECK_EQ(0u, out->avail_in);
944 DCHECK_LT(0u, out->avail_out);
947 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
948 out->avail_in = data.size();
950 if (clas == kZStandardData) {
951 rv = deflate(out, Z_NO_FLUSH);
953 rv = deflate(out, Z_PARTIAL_FLUSH);
956 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
959 DCHECK_EQ(0u, out->avail_in);
960 DCHECK_LT(0u, out->avail_out);
963 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
964 static void WriteLengthZ(size_t n,
969 DCHECK_LE(length, sizeof(buf));
970 for (unsigned i = 1; i <= length; i++) {
974 WriteZ(base::StringPiece(buf, length), clas, out);
977 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
978 // manner that resists the length of the compressed data from compromising
980 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
982 unsigned length_length = 4;
983 if (spdy_version_ < 3)
986 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
988 std::map<std::string, std::string>::const_iterator it;
989 for (it = headers->begin(); it != headers->end(); ++it) {
990 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
991 WriteZ(it->first, kZStandardData, z);
993 if (it->first == "cookie") {
994 // We require the cookie values (save for the last) to end with a
995 // semicolon and (save for the first) to start with a space. This is
996 // typically the format that we are given them in but we reserialize them
999 std::vector<base::StringPiece> cookie_values;
1000 size_t cookie_length = 0;
1001 base::StringPiece cookie_data(it->second);
1004 while (!cookie_data.empty() &&
1005 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1006 cookie_data.remove_prefix(1);
1008 if (cookie_data.empty())
1012 for (i = 0; i < cookie_data.size(); i++) {
1013 if (cookie_data[i] == ';')
1016 if (i < cookie_data.size()) {
1017 cookie_values.push_back(cookie_data.substr(0, i));
1018 cookie_length += i + 2 /* semicolon and space */;
1019 cookie_data.remove_prefix(i + 1);
1021 cookie_values.push_back(cookie_data);
1022 cookie_length += cookie_data.size();
1023 cookie_data.remove_prefix(i);
1027 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1028 for (size_t i = 0; i < cookie_values.size(); i++) {
1030 // Since zlib will only back-reference complete cookies, a cookie that
1031 // is currently last (and so doesn't have a trailing semicolon) won't
1032 // match if it's later in a non-final position. The same is true of
1033 // the first cookie.
1034 if (i == 0 && cookie_values.size() == 1) {
1035 cookie = cookie_values[i].as_string();
1036 } else if (i == 0) {
1037 cookie = cookie_values[i].as_string() + ";";
1038 } else if (i < cookie_values.size() - 1) {
1039 cookie = " " + cookie_values[i].as_string() + ";";
1041 cookie = " " + cookie_values[i].as_string();
1043 WriteZ(cookie, kZCookieData, z);
1045 } else if (it->first == "accept" ||
1046 it->first == "accept-charset" ||
1047 it->first == "accept-encoding" ||
1048 it->first == "accept-language" ||
1049 it->first == "host" ||
1050 it->first == "version" ||
1051 it->first == "method" ||
1052 it->first == "scheme" ||
1053 it->first == ":host" ||
1054 it->first == ":version" ||
1055 it->first == ":method" ||
1056 it->first == ":scheme" ||
1057 it->first == "user-agent") {
1058 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1059 WriteZ(it->second, kZStandardData, z);
1061 // Non-whitelisted headers are Huffman compressed in their own block, but
1062 // don't match against the window.
1063 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1064 WriteZ(it->second, kZHuffmanOnlyData, z);
1069 int rv = deflate(z, Z_SYNC_FLUSH);
1070 DCHECK_EQ(Z_OK, rv);
1071 z->clas = kZStandardData;
1073 #endif // !defined(USE_SYSTEM_ZLIB)
1075 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1077 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1078 size_t original_len = len;
1080 if (remaining_control_header_ > 0) {
1081 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1082 remaining_control_header_);
1083 remaining_control_header_ -= bytes_read;
1084 remaining_data_length_ -= bytes_read;
1087 if (remaining_control_header_ == 0) {
1088 SpdyFrameReader reader(current_frame_buffer_.get(),
1089 current_frame_buffer_length_);
1090 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1092 switch (current_frame_type_) {
1095 bool successful_read = true;
1096 if (spdy_version_ < 4) {
1097 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1098 DCHECK(successful_read);
1100 if (current_frame_stream_id_ == 0) {
1101 set_error(SPDY_INVALID_CONTROL_FRAME);
1105 SpdyStreamId associated_to_stream_id = kInvalidStream;
1106 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1107 DCHECK(successful_read);
1109 SpdyPriority priority = 0;
1110 successful_read = reader.ReadUInt8(&priority);
1111 DCHECK(successful_read);
1112 if (protocol_version() < 3) {
1113 priority = priority >> 6;
1115 priority = priority >> 5;
1119 if (protocol_version() < 3) {
1120 // SPDY 2 had an unused byte here. Seek past it.
1123 successful_read = reader.ReadUInt8(&slot);
1124 DCHECK(successful_read);
1127 DCHECK(reader.IsDoneReading());
1128 if (debug_visitor_) {
1129 debug_visitor_->OnReceiveCompressedFrame(
1130 current_frame_stream_id_,
1131 current_frame_type_,
1132 current_frame_length_);
1134 visitor_->OnSynStream(
1135 current_frame_stream_id_,
1136 associated_to_stream_id,
1139 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1140 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1142 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1145 visitor_->OnSettings(current_frame_flags_ &
1146 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1147 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1151 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1153 bool successful_read = true;
1154 if (spdy_version_ < 4) {
1155 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1156 DCHECK(successful_read);
1158 if (current_frame_stream_id_ == 0) {
1159 set_error(SPDY_INVALID_CONTROL_FRAME);
1162 if (protocol_version() < 3) {
1163 // SPDY 2 had two unused bytes here. Seek past them.
1166 DCHECK(reader.IsDoneReading());
1167 if (debug_visitor_) {
1168 debug_visitor_->OnReceiveCompressedFrame(
1169 current_frame_stream_id_,
1170 current_frame_type_,
1171 current_frame_length_);
1173 if (current_frame_type_ == SYN_REPLY) {
1174 visitor_->OnSynReply(
1175 current_frame_stream_id_,
1176 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1178 visitor_->OnHeaders(
1179 current_frame_stream_id_,
1180 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1183 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1187 DCHECK_LE(4, protocol_version());
1188 if (current_frame_stream_id_ == 0) {
1189 set_error(SPDY_INVALID_CONTROL_FRAME);
1192 SpdyStreamId promised_stream_id = kInvalidStream;
1193 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1194 DCHECK(successful_read);
1195 DCHECK(reader.IsDoneReading());
1196 if (promised_stream_id == 0) {
1197 set_error(SPDY_INVALID_CONTROL_FRAME);
1200 if (debug_visitor_) {
1201 debug_visitor_->OnReceiveCompressedFrame(
1202 current_frame_stream_id_,
1203 current_frame_type_,
1204 current_frame_length_);
1206 visitor_->OnPushPromise(current_frame_stream_id_, promised_stream_id);
1208 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1214 return original_len - len;
1217 // Does not buffer the control payload. Instead, either passes directly to the
1218 // visitor or decompresses and then passes directly to the visitor, via
1219 // IncrementallyDeliverControlFrameHeaderData() or
1220 // IncrementallyDecompressControlFrameHeaderData() respectively.
1221 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1223 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1225 bool processed_successfully = true;
1226 if (current_frame_type_ != SYN_STREAM &&
1227 current_frame_type_ != SYN_REPLY &&
1228 current_frame_type_ != HEADERS &&
1229 current_frame_type_ != PUSH_PROMISE) {
1230 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1232 size_t process_bytes = std::min(data_len, remaining_data_length_);
1233 if (process_bytes > 0) {
1234 if (enable_compression_) {
1235 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1236 current_frame_stream_id_, data, process_bytes);
1238 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1239 current_frame_stream_id_, data, process_bytes);
1242 remaining_data_length_ -= process_bytes;
1245 // Handle the case that there is no futher data in this frame.
1246 if (remaining_data_length_ == 0 && processed_successfully) {
1247 // The complete header block has been delivered. We send a zero-length
1248 // OnControlFrameHeaderData() to indicate this.
1249 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1251 // If this is a FIN, tell the caller.
1252 if (current_frame_flags_ & CONTROL_FLAG_FIN) {
1253 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1256 CHANGE_STATE(SPDY_AUTO_RESET);
1260 if (!processed_successfully) {
1264 // Return amount processed.
1265 return process_bytes;
1268 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1270 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1271 DCHECK_EQ(SETTINGS, current_frame_type_);
1272 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1273 size_t processed_bytes = 0;
1275 // Loop over our incoming data.
1276 while (unprocessed_bytes > 0) {
1277 // Process up to one setting at a time.
1278 size_t processing = std::min(
1280 static_cast<size_t>(8 - settings_scratch_.setting_buf_len));
1282 // Check if we have a complete setting in our input.
1283 if (processing == 8) {
1284 // Parse the setting directly out of the input without buffering.
1285 if (!ProcessSetting(data + processed_bytes)) {
1286 set_error(SPDY_INVALID_CONTROL_FRAME);
1287 return processed_bytes;
1290 // Continue updating settings_scratch_.setting_buf.
1291 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1292 data + processed_bytes,
1294 settings_scratch_.setting_buf_len += processing;
1296 // Check if we have a complete setting buffered.
1297 if (settings_scratch_.setting_buf_len == 8) {
1298 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1299 set_error(SPDY_INVALID_CONTROL_FRAME);
1300 return processed_bytes;
1302 // Reset settings_scratch_.setting_buf for our next setting.
1303 settings_scratch_.setting_buf_len = 0;
1308 unprocessed_bytes -= processing;
1309 processed_bytes += processing;
1312 // Check if we're done handling this SETTINGS frame.
1313 remaining_data_length_ -= processed_bytes;
1314 if (remaining_data_length_ == 0) {
1315 CHANGE_STATE(SPDY_AUTO_RESET);
1318 return processed_bytes;
1321 bool SpdyFramer::ProcessSetting(const char* data) {
1323 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1324 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1325 SettingsFlagsAndId id_and_flags =
1326 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
1327 uint8 flags = id_and_flags.flags();
1328 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1331 switch (id_and_flags.id()) {
1332 case SETTINGS_UPLOAD_BANDWIDTH:
1333 case SETTINGS_DOWNLOAD_BANDWIDTH:
1334 case SETTINGS_ROUND_TRIP_TIME:
1335 case SETTINGS_MAX_CONCURRENT_STREAMS:
1336 case SETTINGS_CURRENT_CWND:
1337 case SETTINGS_DOWNLOAD_RETRANS_RATE:
1338 case SETTINGS_INITIAL_WINDOW_SIZE:
1342 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
1345 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());
1347 // Detect duplciates.
1348 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
1349 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1350 << " in " << display_protocol_ << " SETTINGS frame "
1351 << "(last settikng id was "
1352 << settings_scratch_.last_setting_id << ").";
1355 settings_scratch_.last_setting_id = id;
1358 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1359 if ((flags & ~(kFlagsMask)) != 0) {
1360 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1365 // Validation succeeded. Pass on to visitor.
1366 visitor_->OnSetting(id, flags, value);
1370 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1371 size_t original_len = len;
1373 UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_);
1374 remaining_data_length_ -= bytes_read;
1375 if (remaining_data_length_ == 0) {
1376 SpdyFrameReader reader(current_frame_buffer_.get(),
1377 current_frame_buffer_length_);
1378 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1380 // Use frame-specific handlers.
1381 switch (current_frame_type_) {
1383 bool successful_read = true;
1384 if (spdy_version_ < 4) {
1385 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1386 DCHECK(successful_read);
1388 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1389 uint32 status_raw = status;
1390 successful_read = reader.ReadUInt32(&status_raw);
1391 DCHECK(successful_read);
1392 if (status_raw > RST_STREAM_INVALID &&
1393 status_raw < RST_STREAM_NUM_STATUS_CODES) {
1394 status = static_cast<SpdyRstStreamStatus>(status_raw);
1396 // TODO(hkhalil): Probably best to OnError here, depending on
1397 // our interpretation of the spec. Keeping with existing liberal
1398 // behavior for now.
1400 DCHECK(reader.IsDoneReading());
1401 visitor_->OnRstStream(current_frame_stream_id_, status);
1406 bool successful_read = reader.ReadUInt32(&id);
1407 DCHECK(successful_read);
1408 DCHECK(reader.IsDoneReading());
1409 visitor_->OnPing(id);
1413 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1414 DCHECK(successful_read);
1415 SpdyGoAwayStatus status = GOAWAY_OK;
1416 if (spdy_version_ >= 3) {
1417 uint32 status_raw = GOAWAY_OK;
1418 successful_read = reader.ReadUInt32(&status_raw);
1419 DCHECK(successful_read);
1420 if (status_raw >= GOAWAY_OK &&
1421 status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) {
1422 status = static_cast<SpdyGoAwayStatus>(status_raw);
1424 // TODO(hkhalil): Probably best to OnError here, depending on
1425 // our interpretation of the spec. Keeping with existing liberal
1426 // behavior for now.
1429 DCHECK(reader.IsDoneReading());
1430 visitor_->OnGoAway(current_frame_stream_id_, status);
1433 case WINDOW_UPDATE: {
1434 uint32 delta_window_size = 0;
1435 bool successful_read = true;
1436 if (spdy_version_ < 4) {
1437 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1438 DCHECK(successful_read);
1440 successful_read = reader.ReadUInt32(&delta_window_size);
1441 DCHECK(successful_read);
1442 DCHECK(reader.IsDoneReading());
1443 visitor_->OnWindowUpdate(current_frame_stream_id_,
1448 DCHECK_LE(4, protocol_version());
1449 DCHECK(reader.IsDoneReading());
1450 visitor_->OnBlocked(current_frame_stream_id_);
1455 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1458 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1460 return original_len - len;
1463 size_t SpdyFramer::ProcessCredentialFramePayload(const char* data, size_t len) {
1465 // Clamp to the actual remaining payload.
1466 if (len > remaining_data_length_) {
1467 len = remaining_data_length_;
1469 bool processed_succesfully = visitor_->OnCredentialFrameData(data, len);
1470 remaining_data_length_ -= len;
1471 if (!processed_succesfully) {
1472 set_error(SPDY_CREDENTIAL_FRAME_CORRUPT);
1473 } else if (remaining_data_length_ == 0) {
1474 visitor_->OnCredentialFrameData(NULL, 0);
1475 CHANGE_STATE(SPDY_AUTO_RESET);
1481 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
1482 size_t original_len = len;
1484 if (remaining_data_length_ > 0) {
1485 size_t amount_to_forward = std::min(remaining_data_length_, len);
1486 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
1487 // Only inform the visitor if there is data.
1488 if (amount_to_forward) {
1489 visitor_->OnStreamFrameData(
1490 current_frame_stream_id_, data, amount_to_forward, false);
1493 data += amount_to_forward;
1494 len -= amount_to_forward;
1495 remaining_data_length_ -= amount_to_forward;
1497 // If the FIN flag is set, and there is no more data in this data
1498 // frame, inform the visitor of EOF via a 0-length data frame.
1499 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
1500 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
1504 if (remaining_data_length_ == 0) {
1505 CHANGE_STATE(SPDY_AUTO_RESET);
1507 return original_len - len;
1510 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
1511 size_t header_length,
1512 SpdyHeaderBlock* block) const {
1513 SpdyFrameReader reader(header_data, header_length);
1515 // Read number of headers.
1517 if (spdy_version_ < 3) {
1519 if (!reader.ReadUInt16(&temp)) {
1520 DLOG(INFO) << "Unable to read number of headers.";
1525 if (!reader.ReadUInt32(&num_headers)) {
1526 DLOG(INFO) << "Unable to read number of headers.";
1531 // Read each header.
1532 for (uint32 index = 0; index < num_headers; ++index) {
1533 base::StringPiece temp;
1535 // Read header name.
1536 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1537 : !reader.ReadStringPiece32(&temp)) {
1538 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of "
1539 << num_headers << ").";
1542 std::string name = temp.as_string();
1544 // Read header value.
1545 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
1546 : !reader.ReadStringPiece32(&temp)) {
1547 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of "
1548 << num_headers << ").";
1551 std::string value = temp.as_string();
1553 // Ensure no duplicates.
1554 if (block->find(name) != block->end()) {
1555 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of "
1556 << num_headers << ").";
1561 (*block)[name] = value;
1563 return reader.GetBytesConsumed();
1567 bool SpdyFramer::ParseCredentialData(const char* data, size_t len,
1568 SpdyCredential* credential) {
1571 SpdyFrameReader parser(data, len);
1572 base::StringPiece temp;
1573 if (!parser.ReadUInt16(&credential->slot)) {
1577 if (!parser.ReadStringPiece32(&temp)) {
1580 credential->proof = temp.as_string();
1582 while (!parser.IsDoneReading()) {
1583 if (!parser.ReadStringPiece32(&temp)) {
1586 credential->certs.push_back(temp.as_string());
1591 SpdyFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
1593 uint32 len, SpdyDataFlags flags) const {
1594 DCHECK_EQ(0, flags & (!DATA_FLAG_FIN));
1596 SpdyDataIR data_ir(stream_id, base::StringPiece(data, len));
1597 data_ir.set_fin(flags & DATA_FLAG_FIN);
1598 return SerializeData(data_ir);
1601 SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
1602 const size_t kSize = GetDataFrameMinimumSize() + data.data().length();
1604 SpdyDataFlags flags = DATA_FLAG_NONE;
1606 flags = DATA_FLAG_FIN;
1609 SpdyFrameBuilder builder(kSize);
1610 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1611 builder.WriteBytes(data.data().data(), data.data().length());
1612 DCHECK_EQ(kSize, builder.length());
1613 return builder.take();
1616 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
1617 const SpdyDataIR& data) const {
1618 const size_t kSize = GetDataFrameMinimumSize();
1620 SpdyDataFlags flags = DATA_FLAG_NONE;
1622 flags = DATA_FLAG_FIN;
1625 SpdyFrameBuilder builder(kSize);
1626 builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
1627 if (protocol_version() < 4) {
1628 builder.OverwriteLength(*this, data.data().length());
1630 builder.OverwriteLength(*this, data.data().length() + kSize);
1632 DCHECK_EQ(kSize, builder.length());
1633 return builder.take();
1636 SpdyFrame* SpdyFramer::CreateSynStream(
1637 SpdyStreamId stream_id,
1638 SpdyStreamId associated_stream_id,
1639 SpdyPriority priority,
1640 uint8 credential_slot,
1641 SpdyControlFlags flags,
1643 const SpdyHeaderBlock* headers) {
1644 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL);
1645 DCHECK_EQ(enable_compression_, compressed);
1647 SpdySynStreamIR syn_stream(stream_id);
1648 syn_stream.set_associated_to_stream_id(associated_stream_id);
1649 syn_stream.set_priority(priority);
1650 syn_stream.set_slot(credential_slot);
1651 syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
1652 syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1653 // TODO(hkhalil): Avoid copy here.
1654 *(syn_stream.GetMutableNameValueBlock()) = *headers;
1656 return SerializeSynStream(syn_stream);
1659 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
1660 const SpdySynStreamIR& syn_stream) {
1662 if (syn_stream.fin()) {
1663 flags |= CONTROL_FLAG_FIN;
1665 if (syn_stream.unidirectional()) {
1666 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
1669 // The size of this frame, including variable-length name-value block.
1670 const size_t size = GetSynStreamMinimumSize()
1671 + GetSerializedLength(syn_stream.name_value_block());
1673 SpdyFrameBuilder builder(size);
1674 if (spdy_version_ < 4) {
1675 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
1676 builder.WriteUInt32(syn_stream.stream_id());
1678 builder.WriteFramePrefix(*this,
1681 syn_stream.stream_id());
1683 builder.WriteUInt32(syn_stream.associated_to_stream_id());
1684 uint8 priority = syn_stream.priority();
1685 if (priority > GetLowestPriority()) {
1686 DLOG(DFATAL) << "Priority out-of-bounds.";
1687 priority = GetLowestPriority();
1689 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
1690 builder.WriteUInt8(syn_stream.slot());
1691 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
1692 SerializeNameValueBlock(&builder, syn_stream);
1694 if (debug_visitor_) {
1695 const size_t payload_len = GetSerializedLength(
1696 protocol_version(), &(syn_stream.name_value_block()));
1697 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
1703 return builder.take();
1706 SpdyFrame* SpdyFramer::CreateSynReply(
1707 SpdyStreamId stream_id,
1708 SpdyControlFlags flags,
1710 const SpdyHeaderBlock* headers) {
1711 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN);
1712 DCHECK_EQ(enable_compression_, compressed);
1714 SpdySynReplyIR syn_reply(stream_id);
1715 syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
1716 // TODO(hkhalil): Avoid copy here.
1717 *(syn_reply.GetMutableNameValueBlock()) = *headers;
1719 return SerializeSynReply(syn_reply);
1722 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
1723 const SpdySynReplyIR& syn_reply) {
1725 if (syn_reply.fin()) {
1726 flags |= CONTROL_FLAG_FIN;
1729 // The size of this frame, including variable-length name-value block.
1730 size_t size = GetSynReplyMinimumSize()
1731 + GetSerializedLength(syn_reply.name_value_block());
1733 SpdyFrameBuilder builder(size);
1734 if (spdy_version_ < 4) {
1735 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
1736 builder.WriteUInt32(syn_reply.stream_id());
1738 builder.WriteFramePrefix(*this,
1741 syn_reply.stream_id());
1743 if (protocol_version() < 3) {
1744 builder.WriteUInt16(0); // Unused.
1746 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
1747 SerializeNameValueBlock(&builder, syn_reply);
1749 if (debug_visitor_) {
1750 const size_t payload_len = GetSerializedLength(
1751 protocol_version(), &(syn_reply.name_value_block()));
1752 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
1758 return builder.take();
1761 SpdyFrame* SpdyFramer::CreateRstStream(
1762 SpdyStreamId stream_id,
1763 SpdyRstStreamStatus status) const {
1764 SpdyRstStreamIR rst_stream(stream_id, status);
1765 return SerializeRstStream(rst_stream);
1768 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
1769 const SpdyRstStreamIR& rst_stream) const {
1770 SpdyFrameBuilder builder(GetRstStreamSize());
1771 if (spdy_version_ < 4) {
1772 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
1773 builder.WriteUInt32(rst_stream.stream_id());
1775 builder.WriteFramePrefix(*this,
1778 rst_stream.stream_id());
1780 builder.WriteUInt32(rst_stream.status());
1781 DCHECK_EQ(GetRstStreamSize(), builder.length());
1782 return builder.take();
1785 SpdyFrame* SpdyFramer::CreateSettings(
1786 const SettingsMap& values) const {
1787 SpdySettingsIR settings;
1788 for (SettingsMap::const_iterator it = values.begin();
1791 settings.AddSetting(it->first,
1792 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
1793 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
1796 return SerializeSettings(settings);
1799 SpdySerializedFrame* SpdyFramer::SerializeSettings(
1800 const SpdySettingsIR& settings) const {
1802 if (settings.clear_settings()) {
1803 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
1805 const SpdySettingsIR::ValueMap* values = &(settings.values());
1807 // Size, in bytes, of this SETTINGS frame.
1808 const size_t size = GetSettingsMinimumSize() + (values->size() * 8);
1810 SpdyFrameBuilder builder(size);
1811 if (spdy_version_ < 4) {
1812 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
1814 builder.WriteFramePrefix(*this, SETTINGS, flags, 0);
1816 builder.WriteUInt32(values->size());
1817 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
1818 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
1819 it != values->end();
1821 uint8 setting_flags = 0;
1822 if (it->second.persist_value) {
1823 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
1825 if (it->second.persisted) {
1826 setting_flags |= SETTINGS_FLAG_PERSISTED;
1828 SettingsFlagsAndId flags_and_id(setting_flags, it->first);
1829 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
1830 builder.WriteBytes(&id_and_flags_wire, 4);
1831 builder.WriteUInt32(it->second.value);
1833 DCHECK_EQ(size, builder.length());
1834 return builder.take();
1837 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
1838 DCHECK_LE(4, protocol_version());
1839 SpdyFrameBuilder builder(GetBlockedSize());
1840 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id());
1841 return builder.take();
1844 SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const {
1845 SpdyPingIR ping(unique_id);
1846 return SerializePing(ping);
1849 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
1850 SpdyFrameBuilder builder(GetPingSize());
1851 if (spdy_version_ < 4) {
1852 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
1854 builder.WriteFramePrefix(*this, PING, 0, 0);
1856 builder.WriteUInt32(ping.id());
1857 DCHECK_EQ(GetPingSize(), builder.length());
1858 return builder.take();
1861 SpdyFrame* SpdyFramer::CreateGoAway(
1862 SpdyStreamId last_accepted_stream_id,
1863 SpdyGoAwayStatus status) const {
1864 SpdyGoAwayIR goaway(last_accepted_stream_id, status);
1865 return SerializeGoAway(goaway);
1868 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
1869 const SpdyGoAwayIR& goaway) const {
1870 SpdyFrameBuilder builder(GetGoAwaySize());
1871 if (spdy_version_ < 4) {
1872 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
1874 builder.WriteFramePrefix(*this, GOAWAY, 0, 0);
1876 builder.WriteUInt32(goaway.last_good_stream_id());
1877 if (protocol_version() >= 3) {
1878 builder.WriteUInt32(goaway.status());
1880 DCHECK_EQ(GetGoAwaySize(), builder.length());
1881 return builder.take();
1884 SpdyFrame* SpdyFramer::CreateHeaders(
1885 SpdyStreamId stream_id,
1886 SpdyControlFlags flags,
1888 const SpdyHeaderBlock* header_block) {
1889 // Basically the same as CreateSynReply().
1890 DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN));
1891 DCHECK_EQ(enable_compression_, compressed);
1893 SpdyHeadersIR headers(stream_id);
1894 headers.set_fin(flags & CONTROL_FLAG_FIN);
1895 // TODO(hkhalil): Avoid copy here.
1896 *(headers.GetMutableNameValueBlock()) = *header_block;
1898 return SerializeHeaders(headers);
1901 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
1902 const SpdyHeadersIR& headers) {
1904 if (headers.fin()) {
1905 flags |= CONTROL_FLAG_FIN;
1908 // The size of this frame, including variable-length name-value block.
1909 size_t size = GetHeadersMinimumSize()
1910 + GetSerializedLength(headers.name_value_block());
1912 SpdyFrameBuilder builder(size);
1913 if (spdy_version_ < 4) {
1914 builder.WriteControlFrameHeader(*this, HEADERS, flags);
1915 builder.WriteUInt32(headers.stream_id());
1917 builder.WriteFramePrefix(*this,
1920 headers.stream_id());
1922 if (protocol_version() < 3) {
1923 builder.WriteUInt16(0); // Unused.
1925 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
1927 SerializeNameValueBlock(&builder, headers);
1929 if (debug_visitor_) {
1930 const size_t payload_len = GetSerializedLength(
1931 protocol_version(), &(headers.name_value_block()));
1932 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
1938 return builder.take();
1941 SpdyFrame* SpdyFramer::CreateWindowUpdate(
1942 SpdyStreamId stream_id,
1943 uint32 delta_window_size) const {
1944 SpdyWindowUpdateIR window_update(stream_id, delta_window_size);
1945 return SerializeWindowUpdate(window_update);
1948 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
1949 const SpdyWindowUpdateIR& window_update) const {
1950 SpdyFrameBuilder builder(GetWindowUpdateSize());
1951 if (spdy_version_ < 4) {
1952 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
1953 builder.WriteUInt32(window_update.stream_id());
1955 builder.WriteFramePrefix(*this,
1958 window_update.stream_id());
1960 builder.WriteUInt32(window_update.delta());
1961 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
1962 return builder.take();
1965 // TODO(hkhalil): Gut with SpdyCredential removal.
1966 SpdyFrame* SpdyFramer::CreateCredentialFrame(
1967 const SpdyCredential& credential) const {
1968 SpdyCredentialIR credential_ir(credential.slot);
1969 credential_ir.set_proof(credential.proof);
1970 for (std::vector<std::string>::const_iterator cert = credential.certs.begin();
1971 cert != credential.certs.end();
1973 credential_ir.AddCertificate(*cert);
1975 return SerializeCredential(credential_ir);
1978 SpdySerializedFrame* SpdyFramer::SerializeCredential(
1979 const SpdyCredentialIR& credential) const {
1980 size_t size = GetCredentialMinimumSize();
1981 size += 4 + credential.proof().length(); // Room for proof.
1982 for (SpdyCredentialIR::CertificateList::const_iterator it =
1983 credential.certificates()->begin();
1984 it != credential.certificates()->end();
1986 size += 4 + it->length(); // Room for certificate.
1989 SpdyFrameBuilder builder(size);
1990 if (spdy_version_ < 4) {
1991 builder.WriteControlFrameHeader(*this, CREDENTIAL, kNoFlags);
1993 builder.WriteFramePrefix(*this, CREDENTIAL, kNoFlags, 0);
1995 builder.WriteUInt16(credential.slot());
1996 DCHECK_EQ(GetCredentialMinimumSize(), builder.length());
1997 builder.WriteStringPiece32(credential.proof());
1998 for (SpdyCredentialIR::CertificateList::const_iterator it =
1999 credential.certificates()->begin();
2000 it != credential.certificates()->end();
2002 builder.WriteStringPiece32(*it);
2004 DCHECK_EQ(size, builder.length());
2005 return builder.take();
2008 SpdyFrame* SpdyFramer::CreatePushPromise(
2009 SpdyStreamId stream_id,
2010 SpdyStreamId promised_stream_id,
2011 const SpdyHeaderBlock* header_block) {
2012 SpdyPushPromiseIR push_promise(stream_id, promised_stream_id);
2013 // TODO(hkhalil): Avoid copy here.
2014 *(push_promise.GetMutableNameValueBlock()) = *header_block;
2016 return SerializePushPromise(push_promise);
2019 SpdyFrame* SpdyFramer::SerializePushPromise(
2020 const SpdyPushPromiseIR& push_promise) {
2021 DCHECK_LE(4, protocol_version());
2022 // The size of this frame, including variable-length name-value block.
2023 size_t size = GetPushPromiseMinimumSize()
2024 + GetSerializedLength(push_promise.name_value_block());
2026 SpdyFrameBuilder builder(size);
2027 builder.WriteFramePrefix(*this, PUSH_PROMISE, kNoFlags,
2028 push_promise.stream_id());
2029 builder.WriteUInt32(push_promise.promised_stream_id());
2030 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2032 SerializeNameValueBlock(&builder, push_promise);
2034 if (debug_visitor_) {
2035 const size_t payload_len = GetSerializedLength(
2036 protocol_version(), &(push_promise.name_value_block()));
2037 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2038 PUSH_PROMISE, payload_len, builder.length());
2041 return builder.take();
2046 class FrameSerializationVisitor : public SpdyFrameVisitor {
2048 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
2049 virtual ~FrameSerializationVisitor() {}
2051 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2053 virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2054 frame_.reset(framer_->SerializeData(data));
2056 virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2057 frame_.reset(framer_->SerializeSynStream(syn_stream));
2059 virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2060 frame_.reset(framer_->SerializeSynReply(syn_reply));
2062 virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2063 frame_.reset(framer_->SerializeRstStream(rst_stream));
2065 virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2066 frame_.reset(framer_->SerializeSettings(settings));
2068 virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2069 frame_.reset(framer_->SerializePing(ping));
2071 virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2072 frame_.reset(framer_->SerializeGoAway(goaway));
2074 virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2075 frame_.reset(framer_->SerializeHeaders(headers));
2077 virtual void VisitWindowUpdate(
2078 const SpdyWindowUpdateIR& window_update) OVERRIDE {
2079 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2081 virtual void VisitCredential(const SpdyCredentialIR& credential) OVERRIDE {
2082 frame_.reset(framer_->SerializeCredential(credential));
2084 virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2085 frame_.reset(framer_->SerializeBlocked(blocked));
2087 virtual void VisitPushPromise(
2088 const SpdyPushPromiseIR& push_promise) OVERRIDE {
2089 frame_.reset(framer_->SerializePushPromise(push_promise));
2093 SpdyFramer* framer_;
2094 scoped_ptr<SpdySerializedFrame> frame_;
2099 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2100 FrameSerializationVisitor visitor(this);
2101 frame.Visit(&visitor);
2102 return visitor.ReleaseSerializedFrame();
2105 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2106 const size_t uncompressed_length =
2107 GetSerializedLength(protocol_version(), &headers);
2108 if (!enable_compression_) {
2109 return uncompressed_length;
2111 z_stream* compressor = GetHeaderCompressor();
2112 // Since we'll be performing lots of flushes when compressing the data,
2113 // zlib's lower bounds may be insufficient.
2114 return 2 * deflateBound(compressor, uncompressed_length);
2117 // The following compression setting are based on Brian Olson's analysis. See
2118 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
2119 // for more details.
2120 #if defined(USE_SYSTEM_ZLIB)
2121 // System zlib is not expected to have workaround for http://crbug.com/139744,
2122 // so disable compression in that case.
2123 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
2124 static const int kCompressorLevel = 0;
2125 #else // !defined(USE_SYSTEM_ZLIB)
2126 static const int kCompressorLevel = 9;
2127 #endif // !defined(USE_SYSTEM_ZLIB)
2128 static const int kCompressorWindowSizeInBits = 11;
2129 static const int kCompressorMemLevel = 1;
2131 z_stream* SpdyFramer::GetHeaderCompressor() {
2132 if (header_compressor_.get())
2133 return header_compressor_.get(); // Already initialized.
2135 header_compressor_.reset(new z_stream);
2136 memset(header_compressor_.get(), 0, sizeof(z_stream));
2138 int success = deflateInit2(header_compressor_.get(),
2141 kCompressorWindowSizeInBits,
2142 kCompressorMemLevel,
2143 Z_DEFAULT_STRATEGY);
2144 if (success == Z_OK) {
2145 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2147 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2148 : kV3DictionarySize;
2149 success = deflateSetDictionary(header_compressor_.get(),
2150 reinterpret_cast<const Bytef*>(dictionary),
2153 if (success != Z_OK) {
2154 LOG(WARNING) << "deflateSetDictionary failure: " << success;
2155 header_compressor_.reset(NULL);
2158 return header_compressor_.get();
2161 z_stream* SpdyFramer::GetHeaderDecompressor() {
2162 if (header_decompressor_.get())
2163 return header_decompressor_.get(); // Already initialized.
2165 header_decompressor_.reset(new z_stream);
2166 memset(header_decompressor_.get(), 0, sizeof(z_stream));
2168 int success = inflateInit(header_decompressor_.get());
2169 if (success != Z_OK) {
2170 LOG(WARNING) << "inflateInit failure: " << success;
2171 header_decompressor_.reset(NULL);
2174 return header_decompressor_.get();
2177 // Incrementally decompress the control frame's header block, feeding the
2178 // result to the visitor in chunks. Continue this until the visitor
2179 // indicates that it cannot process any more data, or (more commonly) we
2180 // run out of data to deliver.
2181 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
2182 SpdyStreamId stream_id,
2185 // Get a decompressor or set error.
2186 z_stream* decomp = GetHeaderDecompressor();
2187 if (decomp == NULL) {
2188 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
2189 set_error(SPDY_DECOMPRESS_FAILURE);
2193 bool processed_successfully = true;
2194 char buffer[kHeaderDataChunkMaxSize];
2196 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
2197 decomp->avail_in = len;
2198 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
2199 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
2200 // reached this method successfully, stream_id should be nonzero.
2201 DCHECK_LT(0u, stream_id);
2202 while (decomp->avail_in > 0 && processed_successfully) {
2203 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
2204 decomp->avail_out = arraysize(buffer);
2206 int rv = inflate(decomp, Z_SYNC_FLUSH);
2207 if (rv == Z_NEED_DICT) {
2208 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
2210 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
2211 : kV3DictionarySize;
2212 const DictionaryIds& ids = g_dictionary_ids.Get();
2213 const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
2214 : ids.v3_dictionary_id;
2215 // Need to try again with the right dictionary.
2216 if (decomp->adler == dictionary_id) {
2217 rv = inflateSetDictionary(decomp,
2218 reinterpret_cast<const Bytef*>(dictionary),
2221 rv = inflate(decomp, Z_SYNC_FLUSH);
2225 // Inflate will generate a Z_BUF_ERROR if it runs out of input
2226 // without producing any output. The input is consumed and
2227 // buffered internally by zlib so we can detect this condition by
2228 // checking if avail_in is 0 after the call to inflate.
2229 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
2230 if ((rv == Z_OK) || input_exhausted) {
2231 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
2232 if (decompressed_len > 0) {
2233 processed_successfully = visitor_->OnControlFrameHeaderData(
2234 stream_id, buffer, decompressed_len);
2236 if (!processed_successfully) {
2237 // Assume that the problem was the header block was too large for the
2239 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2242 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
2243 set_error(SPDY_DECOMPRESS_FAILURE);
2244 processed_successfully = false;
2247 return processed_successfully;
2250 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
2251 SpdyStreamId stream_id, const char* data, size_t len) {
2252 bool read_successfully = true;
2253 while (read_successfully && len > 0) {
2254 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
2255 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
2257 data += bytes_to_deliver;
2258 len -= bytes_to_deliver;
2259 if (!read_successfully) {
2260 // Assume that the problem was the header block was too large for the
2262 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
2265 return read_successfully;
2268 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
2269 SpdyFrameBuilder* builder,
2270 const SpdyNameValueBlock& name_value_block) const {
2271 // Serialize number of headers.
2272 if (protocol_version() < 3) {
2273 builder->WriteUInt16(name_value_block.size());
2275 builder->WriteUInt32(name_value_block.size());
2278 // Serialize each header.
2279 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
2280 it != name_value_block.end();
2282 if (protocol_version() < 3) {
2283 builder->WriteString(it->first);
2284 builder->WriteString(it->second);
2286 builder->WriteStringPiece32(it->first);
2287 builder->WriteStringPiece32(it->second);
2292 void SpdyFramer::SerializeNameValueBlock(
2293 SpdyFrameBuilder* builder,
2294 const SpdyFrameWithNameValueBlockIR& frame) {
2295 if (!enable_compression_) {
2296 return SerializeNameValueBlockWithoutCompression(builder,
2297 frame.name_value_block());
2300 // First build an uncompressed version to be fed into the compressor.
2301 const size_t uncompressed_len = GetSerializedLength(
2302 protocol_version(), &(frame.name_value_block()));
2303 SpdyFrameBuilder uncompressed_builder(uncompressed_len);
2304 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
2305 frame.name_value_block());
2306 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
2308 z_stream* compressor = GetHeaderCompressor();
2310 LOG(DFATAL) << "Could not obtain compressor.";
2314 base::StatsCounter compressed_frames("spdy.CompressedFrames");
2315 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
2316 base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
2318 // Create an output frame.
2319 // Since we'll be performing lots of flushes when compressing the data,
2320 // zlib's lower bounds may be insufficient.
2322 // TODO(akalin): Avoid the duplicate calculation with
2323 // GetSerializedLength(const SpdyHeaderBlock&).
2324 const int compressed_max_size =
2325 2 * deflateBound(compressor, uncompressed_len);
2327 // TODO(phajdan.jr): Clean up after we no longer need
2328 // to workaround http://crbug.com/139744.
2329 #if defined(USE_SYSTEM_ZLIB)
2330 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
2331 compressor->avail_in = uncompressed_len;
2332 #endif // defined(USE_SYSTEM_ZLIB)
2333 compressor->next_out = reinterpret_cast<Bytef*>(
2334 builder->GetWritableBuffer(compressed_max_size));
2335 compressor->avail_out = compressed_max_size;
2337 // TODO(phajdan.jr): Clean up after we no longer need
2338 // to workaround http://crbug.com/139744.
2339 #if defined(USE_SYSTEM_ZLIB)
2340 int rv = deflate(compressor, Z_SYNC_FLUSH);
2341 if (rv != Z_OK) { // How can we know that it compressed everything?
2342 // This shouldn't happen, right?
2343 LOG(WARNING) << "deflate failure: " << rv;
2344 // TODO(akalin): Upstream this return.
2348 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
2349 #endif // defined(USE_SYSTEM_ZLIB)
2351 int compressed_size = compressed_max_size - compressor->avail_out;
2352 builder->Seek(compressed_size);
2353 builder->RewriteLength(*this);
2355 pre_compress_bytes.Add(uncompressed_len);
2356 post_compress_bytes.Add(compressed_size);
2358 compressed_frames.Increment();